Agenda
Este minicurso de R será focado no tidyverse (universo
“arrumado”), que conta com um conjunto de pacotes que auxiliam os
pesquisadores a manipularem suas bases de dados, preparando-as para que
análises possam ser realizadas. Ajustar a base de dados, geralmente, é a
etapa que mais consome tempo em uma pesquisa. Portanto, ter uma
ferramenta que torne essa tarefa mais eficiente é fundamental.
Informações mais aprofundadas sobre o tidyverse estão
disponíveis livro R for data
science.
Esse curso foi baseado nos cursos R pragmático e Curso de R, que podem ser consultados sempre que necessário. O livro R para cientistas sociais é uma outra boa fonte de informações. Para análise de dados com estatística aplicada, o livro Estatística Básica - Bussab e Morettin (2017) conta com um site com os exemplos apresentados no livro. O site do institute for digital research and education, da UCLA conta com valiosos tutoriais que podem ser consultados sempre que necessário para a aplicação de técnicas estatísticas no R. Para análise de pesquisas amostrais complexas, o site do Anthony Joseph Damico é uma formidável fonte de consulta (que contempla as pesquisas do IBGE).
Público-alvo
- Pesquisadores do IPEA
Requisitos básicos:
- Noções de lógica de programação.
- Noções básicas de estatística.
- Noções básicas de inglês (para facilitar pesquisas e entendimento das funções).
Conteúdo:
- Introdução ao R;
- Projetos com controle de versão pelo Github;
- Acesso ao banco de dados da COMEQ;
- Carga da Pesquisa Nacional por Amostra de Domicílios Contínua;
- Introdução ao
tidyverse; - Operador
pipe, manipulação de textos com o pacotestringre datas com o pacotelubridate; - Transformação de dados com
dplyretidyr; - Visualização de dados com
ggplot2; - Elaboração de mapas com auxílio do pacote
sf; - Atualização de valores monetários utilizando o pacote
sidrar; - Acesso aos dados do ipea data no R, com o pacote
ipeadatar; - Utilização dos pacotes
surveyesrvyrpara pesquisas amostrais; - Elaboração de relatórios com o
Rmarkdown.
Introdução
Como surgiu o R e quem o utiliza hoje?
Por que usar o R e não outros softwares?
O R é um sistema para estatística computacional e gráfica;
Um dos focos do R é análise de dados e a interatividade. Isso faz com que o R seja uma linguagem intuitiva e flexível;
Código aberto: sem pirataria!
Constantemente atualizado;
Comunidade ativa e cada vez mais ampla (estatística, economia, sociologia, psicologia, biologia etc.);
O R possui a possibilidade de adotar diversos pacotes. Estes pacotes são coleções de funções e/ou bases de dados desenvolvidos pela comunidade que utiliza a ferramenta. Os pacotes ficam disponíveis no CRAN – Comprehensive R Archive Network – que nada mais é do que uma coleção de sites da linguagem R e seus documentos relacionados;
Versatilidade para integração com outras linguagens e ferramentas. Já é possível rodar python diretamente no RStudio (o RStudio agora é Posit; acesse https://posit.co/ para mais informações);
As versões mais recentes do R podem ser baixadas neste site.
Debilidades do R
O R é, em muitos casos, preterido por programadores no desenvolvimento de aplicações (por exemplo, sua linguagem não se aproxima tanto da linguagem utilizada por esses profissionais quanto o python);
Para alguns pacotes, a documentação pode não ser tão clara ou detalhada quanto a existente em outras ferramentas (como o Stata, por exemplo);
Nem sempre é fácil interpretar as mensagens de erro. Nesses casos, o código aberto permite rastrear todos os passos executados, auxiliando as depurações. Todavia, isso nem sempre é uma tarefa trivial;
Por ser uma ferramenta de código aberto, o suporte para problemas é baseado na comunidade. Não existe uma entidade que fique responsável por prover soluções. Contudo, a comunidade do R é muito ampla e prestativa, minimizando esse tipo de situação;
Também por ser código aberto, nem todos os pacotes recebem atualizações periódicas, podendo sofrer problemas de compatibilidade ou obsolescência ao longo do tempo;
A instalação de alguns pacotes e ferramentas pode ser complicada, exigindo algum conhecimento mais avançado dos usuários conforme a plataforma utilizada;
Devido aos itens anteriores, a reprodutibilidade de alguns scripts pode ficar comprometida. Guardar informações da sessão em que o código foi executado pode mitigar essa situação (versão do R, da platarforma e dos pacotes utilizado). O gerenciamento centralizado do RStudio Server, por exemplo, contribui para minimizar esse tipo de ocorrência.
RStudio
O RStudio é um ambiente integrado de desenvolvimento (integrated development environment – IDE) para a linguagem R e outras (como o Python). Ele ajuda a organizar os trabalhos desenvolvidos, dividindo os conteúdos em janelas. Ele, por exemplo, tem recursos que facilitam a escrita dos códigos (com atalhos de teclado e o recurso de autocompletar). Além disso, possibilita que algumas funções sejam utilizadas via point-and-click. Acesse essa página para maiores informações (em inglês).
Para baixar o RStudio, acesse este site.
Um recurso muito importante do RStudio, amplamente utilizado nas instituições, é a possibilidade de criar projetos com controle de versão, por meio, por exemplo, do Github ou Gitlab. Todos os pacotes do R, por exemplo, estão armazenados publicamente no Github.
RStudio Server
A COMEQ conta com o RStudio server, o que significa que você pode acessar e trabalhar de qualquer máquina conectada à rede do IPEA diretamente do navegador. Clique aqui para acessar o servidor.
Uma vantagem de utilizar o Rserver é sua maior capacidade de processamento, quando comparado com as máquinas locais, contando atualmente com XXGB de memória RAM e um processador de XX núcleos.
Além disso, os pacotes instalados para a realização de um projeto ficam disponíveis para os demais usuários do instituto, sendo periodicamente atualizados pelo administrador do servidor. Isso facilita a reprodutibilidade dos códigos escritos por outros usuários, auxiliando também na continuidade de pesquisas e projetos. Sempre que precisar instalar um pacote, comunique o administrador do servidor [thiago.rosa@ipea.gov.br] para que ele também fique disponível para os demais usuários. Caso você necessite um pacote que demande alguma atualização do servidor, contate o administrador do servidor explicando os detalhes.
Banco de dados da COMEQ
Em 2023, a COMEQ lançou a iniciativa de organizar dados regionalizáveis em um banco de dados próprio, deixando-as prontas para uso e disponíveis a qualquer pesquisador do IPEA. Inicialmente, a principal fonte de informação advém das pesquisas do IBGE. Entretanto, a intenção é tornar disponível todas as bases que a COMEQ julgar conveniente para agilizar as atividades de seus pesquisadores. A vantagem de se utilizar um banco de dados centralizado é que todos os pesquisadores usam a mesma fonte de informação para a produção de relatórios, garantindo consistência aos produtos gerados.
Além disso, as bases utilizadas em um trabalho ficam à disposição dos demais pesquisadores do insituto, evitando o tráfego de informações localmente, redundancias e otimizando os recursos tecnológicos do IPEA. Quanto mais usuários estiverem utilizando a mesma fonte de dados, mais fácil fica para validar as informações e proceder eventuais correções, beneficiando todos os usuários.
Atualmente, o banco conta com as seguintes informações:
- PNADC trimestral
- PNADC anual
- Malhas territoriais do IBGE
- IDHs municipais
- Índice firjan
- Projeções populacionais
- PIB municipal
- Comparecimento eleitoral
- Contas anuais estaduais
- Pagamentos e beneficioários do Bolsa Família e do BPC
- Aeródromos brasileiros
As informações armazenadas no banco de dados podem ser facilmente
carregadas pelo R (ou na maioria dos demais pacotes estatístico, como
STATA ou SAS), por conexão ODBC – acrônimo para Open Database
Connectivity. O RStudio server já está configurado para fazer esta
conexão, enquanto as máquinas locais podem ser facilmente configuradas
seguindo esses
passos. As bases podem ser acessadas com os pacotes
RODBC ou DBI, através de consultas SQL
(Structured Query Language), que nada mais é que uma linguagem
estruturada para realizar consultas em bancos de dados.
GitHub
O GitHub é uma plataforma online de compartilhamento e armazenamento de códigos. Os projetos do GitHub são baseados no git, uma ferramenta de versionamento de software.
O IPEA possui um gitlab para gerenciar e versionar seus projetos, de modo a mantê-los organizados e atualizados, sem o risco de perder informações acidentalmente ou por alguma falha técnica. Outra vantagem é a característica colaborativa da plataforma, permitindo o acesso aos códigos de qualquer lugar, via internet, por outros pesquisadores. Se o repositório for público, qualquer pessoa pode contribuir com os projetos, proporcionando ganhos a todos os futuros usuários. Verifique com o suporte técnico como utilizar a ferramenta.
RMarkdown
O Markdown é um sistema para tornar a escrita e a leitura de textos mais simples. Ele adiciona as formatações correspondentes à estrutura na qual você deseja apresentar seu texto. Tudo isso é feito de maneira simplificada, através de símbolos de teclado.
No R, o RMarkdown, é um tipo de documento especial que contém tanto
textos, no formato markdown, quanto códigos, em R (ou outras linguagens,
como SQL e python). Os códigos em R podem ser inseridos diretamente no
texto, entre dois acentos graves e seguidos da letra r, ou
separados em estruturas específicas (chunks). Os códigos são
executados sempre que o documento é processado para algum formato
específico, que pode ser HTML (como esse documento que você está lendo),
em PDF (formato \(\LaTeX\)) ou mesmo
microsoft Word. Apresentações de slides também podem ser facilmente
realizadas com o Rmarkdown, nos formatos HTML, PDF (\(\LaTeX\)) ou microsoft Power Point.
Suas principais vantagens são a velocidade, reprodutibilidade e eficiência na produção destes relatórios.
Para detalhes sobre como utilizar o RMarkdown, acesse esse e esse sites (em inglês).
Preliminares
Como instalar o R em uma máquina
Para instalar o R, acesse o site do R-project. Escolha sua plataforma e siga os passos para efetuar a instalação.
Se o seu sistema operacionar for Windows, baixe o R base e efetue e instalação. Para instalar alguns pacotes, você irá precisar instalar também o Rtools. Baixe a versão adequada para o seu sistema e efetue a instalação.
Atenção: alguns pacotes necessitam a instalação de outros softwares. Caso algum pacote apresente erro durante a instalação, verifique as mensagens exibidas no console, consulte a documentação do pacote e verifique se os requisitos estão sendo atendidos.
Por fim, baixe e instale o RStudio.
Estrutura do RStudio Server
O primeiro passo é efetuarmos o login no RStudio server da COMEQ Para isso, acesse o site do servidor.
Entre com suas credenciais (u seguido de sua matrícula) e faça o login.
O RStudio server estará dividido em quatro painéis (ou três, caso seja seu primeiro login): o superior à esquerda apresenta os scripts abertos para uso; o inferior à esquerda apresenta o console, local onde os comandos e seus resultados são apresentados. Nesse painel, há também uma aba para o terminal do Linux e uma aba Background Jobs, na qual você pode rodar scripts sem que sua sessão atual seja afetada; o superior direito apresenta o ambiente, com os objetos ativos na sessão. Há mais cinco abas, com o histórico dos comandos executados, as conexões, build (para desenvolvimentos), o Git (se você estiver no ambiente de projetos) e uma aba Tutorial com a qual você pode aprender algumas funcionalidade do R; por fim, o inferior direito apresenta o diretório de trabalho, com as pastas e arquivos. Há ainda mais quatro abas, que apresentam os plots gerados, os pacotes disponíveis na biblioteca, a janela de ajuda e a janela de visualização (utilizadas por alguns pacotes para mostrar conteúdos da web ou em html).
Na parte superior, existe uma barra de tarefas, com a qual você pode
criar novos scripts, projetos, abrir arquivos, executar buscas etc. São
formas de você executar funções por point-and-click. Por
exemplo, você pode alterar a visualização do RStudio server em
Tools -> Global Options... ->
Appereance, ou a disposição das janelas em
View -> Panes.
Por todos os painéis existem atalhos úteis para executar diversas tarefas (abrir um novo script, criar um novo projeto, salvar o script atual, criar uma nova pasta etc.). Aproveite para conhecer essas opções.
Pacotes
Uma das funções mais básicas é instalar e carregar um pacote no R. Por exemplo:
#install.packages("tidyverse") # Instalar o pacote "tidyverse"
library(tidyverse) # Carregar o pacote "tidyverse"
# Siga os passos abaixo para instalar os pacotes utilizados nesse curso
# pacotes <- c("tidyverse","data.table","Hmisc","lubridate",
# "ggrepel","sf","sidrar","survey",
# "srvyr","scales","ggthemr","readxl",
# "kableExtra","psych","xtable")
# if(length(setdiff(pacotes,installed.packages()))==0){}else{
#
# install.packages(setdiff(pacotes,installed.packages()))
#
# }
#devtools::install_github('cttobin/ggthemr')
Note que o caractere # é utilizado para escrever
comentários na codificação. Documentar detalhadamente seu código é
fundamental para que as pessoas que trabalham com você entendam o que
foi realizado. Além disso, é fundamental para que uma tarefa que dependa
desse código possa ser executada ou alterada por outro pesquisador.
Lembre-se que tudo o que produzimos, no fim, é público e deve ser o mais
acessível possível para qualquer pessoa! Para comentar uma série de
linhas ao mesmo tempo, utilize o atalho
Ctrl+Shift+C após
selecioná-las.
Dica: para alterar várias linhas de uma só vez,
segure a tecla Alt e use o cursor para selecionar as
linhas. Desse modo, você conseguirá editar mais rapidamente seus scripts
que demandam repetição de termos. Para mais dicas, acesse esse site,
feito por Paweł Przytuła.
Tão importante quanto utilizar um pacote é citar ele no seu trabalho.
Para tanto, utilize a função citation().
citation("tidyverse")
Operadores básicos
Dentro do R, alguns operadores básicos são constantemente utilizados. Os mais comuns são:
| Operadores | Descrição |
|---|---|
|
|
Adição |
|
|
Subtração |
|
|
Multiplicação |
| / | Divisão |
| ^ ou ** | Exponenciação |
| %% | Resto da divisão |
| %/% | Divisão inteira |
| Operadores | Descrição |
|---|---|
| < | Menor |
| <= | Menor ou igual |
| > | Maior |
| >= | Maior ou igual |
| == | Exatamente igual a |
| != | Não é igual a |
| !X | Não X |
| X|Y | X ou Y |
| X&Y | X e Y |
| Operadores | Descrição |
|---|---|
| x <- valor | Atribuir ‘valor’ a ‘x’ |
| x <<- valor | Atribuir ‘valor’ a ‘x’ |
| valor -> x | Atribuir ‘valor’ a ‘x’ |
| valor ->> x | Atribuir ‘valor’ a ‘x’ |
| x = valor | Atribuir ‘valor’ a ‘x’ |
Algumas teclas de atalho podem ser bastante úteis na hora de escrever os códigos. Veja algumas das principais:
- Ctrl+enter: roda a linha selecionada no script, enviando-a para o console. Um dos atalhos mais utilizado.
- Ctrl+shift+M: (%>%) operador pipe (requer pacote magrittr, carregado com o pacote tidyverse).
- Ctrl+1: altera cursor para o script.
- Ctrl+2: altera cursor para o console.
- Ctrl+Alt+I: cria um chunk dentro de um arquivo RMarkdown.
- Alt+Shift+K: janela com todos os atalhos disponíveis.
- Alt+seleção com mouse: permite que você altere várias linhas de uma única vez.
Agora vamos realizar algumas operações matemáticas básicas com o R. Digite diretamente no console (ou abra um script e escreva os códigos) e utilize o atalho de teclado para rodar o código (você pode também rodar o código com o botão “Run” na parte superior da janela de script).
1 + 2 # Adição
3 - 1 # Subtração
2 * 2 # Multiplicação
1 / 4 # Divisão
O R também realiza testes lógicos. Vamos testar alguns deles.
2+2==4 # 2 + 2 é igual a 4?
2+2==5 # 2 + 2 é igual a 5?
2+2&1+3==4 # 2 + 2 e 1 + 3 são iguais a 4?
2+2|1+4==5 # 2 + 2 ou 1 + 4 são iguais a 5?
No último exemplo testamos se alguma das duas expressões era
verdadeira. Para testar cada uma separadamente, precisamos de uma função
de entrada de vários argumentos simultaneamente. A função utilizada para
combinar é a c(), na qual seus argumentos são separados por
vírgulas. Vamos refazer o último exemplo.
c(2+2,1+4)==5 # 2 + 2 é igual a 5? 1 + 4 é igual a 5?
Agora, o R testa separadamente os dois casos.
Utilizar chamada de funções
As funções no R são palavras específicas seguidas de parenteses
(). Algumas delas estão sempre disponíveis no R (como as
base functions), enquanto outras estão apenas quando os
pacotes são carregados. Vamos ver as funções de soma sum()
e de multiplicação prod().
sum(1,2) # Adição
prod(2,2) # Multiplicação
Algumas funções podem ser chamadas diretamente de seus pacotes, sem
que seja necessário carregá-lo. Para isso, escreva o nome do pacote
instalado, seguido do símbolo ::.
psych::describe(c(1,2)) # Utilizando a função describe, do pacote "psych", sem carregá-lo
Apesar de ser necessário digitar mais caracteres para obter o resultado, chamar funções desta maneira apresenta duas vantagens. A primeira é que fica claro, em cada passo, qual pacote está sendo utilizado para executar determinada tarefa. Em segundo lugar, caso exista algum outro pacote com uma função de mesmo nome, não haverá o risco de utilizarmos a função errada para o problema que estamos tratando (evita-se ambiguidades).
Criar uma função
Você pode criar suas próprias funções do R. Por exemplo, ao invés de
utilizar a função de soma sum, nós podemos criar nossa
própria função para somar dois valores.
# Função para somar dois valores
somar <-
# Abrir argumento para criação de função e informar dentro dos parenteses os parâmetros
function(x,y){
# Construir a operação de soma
z = x + y
# Retornar o resultado
return(z)
}
#Aplicar a função
somar(2,4)
No caso acima, determinamos que a função deve ter dois argumentos,
x e y, os quais serão somados e atribuídos a
variável z, que, por sua vez, será apresentada com a função
return().
Tipos de dados
O R cria seus objetos em diversas classes e tipos. Para as classes,
elas podem ser: lógica, inteiro,
numérico, complexo ou caractere.
Vamos olhar alguns exemplos:
x <- 1L # inteiro
class(x)
x <- 1 # numérico
class(x)
x <- 8i # complexo
class(x)
x <- TRUE # lógico
class(x)
x <- "hello" # character
class(x)
Sobre os tipos, que dizem respeito à estrutura de como as informações
são organizadas, temos, entre outros: vetor,
lista, matriz,
data frame,tibble, fator e
tabela. Vejamos primeiramente o vetor, o mais
simples deles.
x <- c(1,2,3) # Vetor numérico
typeof(x) # Checar o método de armazenagem
class(x) # Checar a classe
length(x) # Checar o tamanho
str(x) # Checar a estrutura
Entre as classes de objetos, sempre que você tentar misturar elementos distintos, o R irá forçar a conversão do vetor para uma classe única. Ele segue a seguinte regra:
DOMINANTE
character > complex > numeric > integer > logical
RECESSIVO
As classes de um vetor poder ser alteradas com as seguintes funções:
x <- 1:10
class(x)
as.numeric(x)
as.logical(x)
as.character(x)
Caso o R não consiga converter algum elemento entre as classes, ele
emitirá um aviso, colocando um valor ausente em seu lugar
(NA - Not Available).
Agora vamos ver uma matriz.
x <- matrix(ncol = 2,nrow = 2) # Criar uma matriz 2 x 2
dim(x) # Checar as dimensões da matriz
x[,] <- c(1,7,9,6) # Atribuir valores à matriz
x <- 1:3 # Contruir um vetor x
y <- 10:12 # Construir um vetor z
z <- cbind(x,y) # Montar uma matriz a partir destes vetores (por colunas)
z <- rbind(x,y) # Montar uma matriz a partir destes vetores (por linhas)
Temos algumas operações úteis para matrizes, como transpor e inverter.
m <- matrix(1:4,ncol = 2,nrow = 2) # Construir a matriz m
n <- matrix(5:8,ncol = 2,nrow = 2) # Construir a matriz n
t(m) # matriz transposta de m
m %*% n # multiplicação matricial de m por n
solve(m) # matriz inversa de m
A lista é um tipo de objeto que pode armazenar diferentes classes em um mesmo local.
lista <- list(1,"paçoca",2i,2.61,TRUE,matrix(1:4)) # Criar uma lista
lista # Checar a lista criada
lista[[2]] # Acessar o segundo elemento da lista
lista <- list(a=1,b="paçoca",c=2i,d=2.61,e=TRUE,f=matrix(1:4)) # Criar uma lista, com nomes dos elementos
Os fatores são particularmente importantes para a apresentação dos
dados e para regressões. Eles servem para tratar vetores categóricos ou
enumeráveis. Vamos ver um exemplo, utilizando logo após a função
table(), para fazer uma tabulação simples dos valores.
# Construir um fator
x <- factor(c("sim","sim","sim","não","sim","não"),levels = c("não","sim"))
table(x) # Tabular os dados
levels(x) # Verificar os níveis dos fatores
class(x) # classe do objeto
# Construir um fator ordenado
x <- factor(c("ruim","bom","ruim","péssimo","ótimo"),
levels = c("péssimo","ruim","bom","ótimo"),
ordered = TRUE)
table(x) # Tabular os dados
levels(x) # Verificar os níveis dos fatores
class(x) # classe do objeto
# Construir um fator de variáveis com códigos
x <- factor(c(1,1,2,1,2,1,2),
levels = c(1,2),
labels = c("Sim","Não"))
table(x) # Tabular os dados
levels(x) # Verificar os níveis dos fatores
class(x) # classe do objeto
x <- factor(c(1,1,2,1,2,1,2,3,4),
levels = c(4,3,2,1),
labels = c("péssimo","ruim","bom","ótimo"),
ordered = TRUE)
table(x) # Tabular os dados
levels(x) # Verificar os níveis dos fatores
class(x) # classe do objeto
As estruturas dos data frames e tibble,
focos deste curso, serão tratadas em detalhes mais adiante, quando
começarmos a manipular a PNADC
Para finalizar, temos alguns números/valores especiais no R:
-Inf, Inf, NA e NaN.
Os dois primeiros se referem ao infinito em ambas as direções, enquanto
os dois últimos são os valores ausentes. Enquanto o NaN se
refere a valores “não numéricos”, funcionando como uma espécie de
“nulo”, os valores ausentes propriamente ditos são da forma
NA, podendo assumir diferentes classes (importante dentro
da função case_when do pacote dplyr). Há ainda
o objeto da classe NULL, que seria um objeto vazio.
Usualmente ele é utilizado em definições de listas com tamanho zero.
1/Inf # Divisão de 1 por infinito
-1/0 # Infinito - divisão de 1 por zero (conceito de limite)
1/0-1/0 # Infinito menos infinito - Indefinido (não numérico)
x <- NA # Missing value (valor ausente)
is.na(x) # Validar se é NA
x <- NULL # Vazio
is.null(x) # Validar se é NULL
Controles de fluxo
Temos algumas estrutura que testam condições e estabelecem fluxos no
R. São exemplos os condicionantes if, else,
for e while.
Podemos fazer um teste lógico para que o R execute uma soma quando
uma condição é atendida. Vejamos uma aplicação do if.
# Criar um objeto com x com o valor 2
x <- 2
# Realizar uma soma se x é igual 2
if(x==2){
x+2
}
# Realizar uma soma se x é igual a 3
if(x==3){
x+2
}
Agora vamos usar o condicionante if juntamente com o
condicionante else.
# Atribuir o valor 8 à x
x <- 8
# Testar se x é positivo ou negativo
if(x < 0) {
"negativo"
} else if(x == 0) {
"zero"
} else if(x > 0) {
"positivo"
}
# Outra maneira de escrever o código
#if(x<0){"negativo"}else if(x==0){"neutro"}else if(x>0){"positivo"}
Note que, sempre que um novo condicionante é adicionado, o RStudio adiciona uma seta para baixo (quando se passa para uma próxima linha), indicando onde se inicia o novo fluxo.
O operador for é utilizado para realizar uma tarefa
baseada em uma lista de valores. Vamos somar uma unidade aos valores
listados entre 5 e 10.
# Criar uma lista de índices
i <- 1:10
# Somar 1 aos valores de 5 a 10
for(i in c(5:10)){
print(i+1)
}
Por fim, temos condicionante while. Ele executa a tarefa
até que uma certa condição seja satisfeita. Por exemplo, vamos somar
duas unidades a x enquanto o resultado é menor ou igual a 10. Esse
condicionante pode ser utilizado, por exemplo, para a maximização de
funções.
x <- 1
while (x<=10) {
print (x)
x=x+2
}
Operador Pipe
Com o R, nós podemos “aninhar” várias funções ao mesmo tempo. Por exemplo, se alguém quiser somar um vetor de números, tirar a raiz quadrada e arrendondar o resultado, podemos fazer tudo isso em uma única linha de comando.
x <- c(1:10) # Criar o vetor numérico
round(sqrt(sum(x))) # Calcular a raíz quadrada da soma do vetor x, arredondando o resultado
Todavia, aninhar várias funções ao mesmo tempo, em algumas situações, pode deixar o código confuso. Vejamos um exemplo de função hipotética para preparação de um bolo.1
# esfrie(asse(coloque(bata(acrescente(recipiente(rep("farinha", 2), "água", "fermento", "leite", "óleo"), "farinha", até = "macio"), duração = "3min"), lugar = "forma", tipo = "grande", untada = T), duração = "50min"), "geladeira", "20min")
Dentro de um mesmo código, é possível indentar as linhas, sempre que um novo argumento da função precisa ser separado por vírgula.
# esfrie(asse(coloque(bata(acrescente(recipiente(rep("farinha", 2),
# "água", "fermento",
# "leite", "óleo"),
# "farinha", até = "macio"),
# duração = "3min"),
# lugar = "forma", tipo = "grande", untada = T),
# duração = "50min"), "geladeira", "20min")
Mesmo assim, ainda resta alguma dificuldade para ler e entender o
código de uma maneira mais clara e fluída. O operador pipe
%>% é utilizado para facilitar a programação e a
leitura, deixando o código mais arrumado. Ele realiza o seguinte
comando, de maneira bastante intuitiva: “use o resultado do lado
esquerdo como argumento da função do lado direito”. Para
utilizá-lo, é necessário carregar algum pacote que leve o operador. Ao
carregar o tidyverse, por exemplo, você já estará apto a
utilizar o pipe (originalmente disponível com o pacote
magrittr).
Vamos testar o operador pipe para calcular novamente a raiz quadrada da soma de um vetor.
x <- c(1:10)
x %>% sum %>% sqrt %>% round
Observe que a escrita fica muito mais intuitiva e elegante. Para o caso do bolo:
# recipiente(rep("farinha", 2), "água", "fermento", "leite", "óleo") %>%
# acrescente("farinha", até = "macio") %>%
# bata(duração = "3min") %>%
# coloque(lugar = "forma", tipo = "grande", untada = T) %>%
# asse(duração = "50min") %>%
# esfrie("geladeira", "20min")
A utilização do pipe será muito importante para a manipulação das bases de dados, uma vez que, geralmente, são necessárias várias sequências de funções até que elas fiquem no formato desejado para análise.
A utilização do pipe se tornou tão popular dentro da linguagem R que,
a partir da versão 4.1, a linguagem trouxe um operador pipe nativo, com
o símbolo |>. Ele, basicamente, faz as mesmas coisas que
o operador original %>% faz. Para algumas diferenças,
consulte esse
artigo. Quando este curso foi concebido, o operador nativo não
existia, portanto, os exemplos aqui tratados utilização o operador
original em seus exemplos. Contudo, utilize aquele de sua preferência.
Você irá notar que, com o R, você terá diversas maneiras de fazer a
mesma coisa!
Onde encontrar ajuda
Há várias maneiras de encontrar ajuda sobre um pacote específico. Por
exemplo, você pode acessar os detalhes da função
psych::describe posicionado o cursor próximo a função e
pressionando a tecla F1.
Uma outra maneira é colocar uma interrogação \(?\) antes da função para a qual se quer
ajuda e executá-la. Uma terceira opção é utilizar a função
help.
?psych::describe
help("describe")
help(describe)
?psych
help("psych")
help(psych)
Para uma pesquisa mais ampla, que irá escanear todos os documentos de
pacotes instalados na sua biblioteca, você pode utilizar o símbolo \(??\) antes da função ou utilizar
diretamente a função help.search
??psych
help.search("psych")
Por fim, outra forma de realizar pesquisas, utilizando a internet, é
com a função RSiteSearch.
RSiteSearch("psych") # Pesquisar um termo
O R é um software de código aberto. Toda e qualquer função pode ser
analisada. Para acessar o código de uma função, posicione o cursor sobre
a função e tecle F2. Você pode acessar a função rodando
somente o nome da função.
psych::describe
Algumas funções são aplicadas por diferentes métodos, como é o caso
da função mean. Para consultar os métodos disponíveis,
utilize a função methods.
methods(mean)
mean.default
mean.difftime
Para consultar uma função em qualquer pacote do R, utilize a função
getAnywhere.
getAnywhere(describe)
getAnywhere(describe)[1]
As funções do tipo .C(), .Call(),
.Fortran(), .External(),
.Internal() ou .Primitive() chamam códigos
compilados, sendo necessário olhar o código fonte. Consulte o manual do R para maiores
informações.
Como alternativa, você pode acessar a página do Github do pacote e
verificar a função diretamente do arquivo .R. Por exemplo,
as funções do pacote base estão disponíveis aqui.
Para uma discussão aprofundada sobre o tema, acesse esse site.
Além disso, no RStudio, você conta com as Cheat Sheets, na
barra superior de ajuda (Help). Você poderá baixar diversos
PDFs com “colas” para as principais operações realizadas na análise de
dados.
As versões mais recentes do RStudio contam com a aba Tutorial, na qual você poderá aprender alguns tópicos diretamente no RStudio.
O site stackoverflow é outra excelente fonte de informação. É muito possível que a dúvida ou o problema que você está encontrando em alguma programação já foi enfrentado por outro usuário. Assim, basta pesquisar sobre sua dúvida neste site (geralmente, feitas e respondidas em inglês).
Por fim, uma boa e velha máquina de buscas é fundamental. Quase todas as repostas você encontrará com sua utilização.
Carga de um arquivo .csv
Vamos iniciar a atividade de manipulação de base de dados carregando
um arquivo .csv encontrado na internet. Vamos trabalhar o
estoque do Tesouro Direto, disponível no site do Tesouro Transparente,
nesse
link.
Vamos carregar a pesquisa de duas maneiras: utilizando os atalhos do
botão do RStudio e por linha de comando, utilizando o pacote
data.table.
Antes, vamos criar um projeto para fazermos nossas análises. Acesse
sua conta no github e crie um novo
repositório. Depois disso, vamos criar um novo projeto no RStudio
server. Para isso, clique em File ->
New project -> Version Control
->Git. No campo Repository URL, cole a url
do projeto que você acabou de criar.
Atenção: você pode copiar o link HTTPS ou
SSH do projeto na página do github. Para um tutorial de como utilizar
autenticação por chave SSH no RStudio, acesse esse site.
Agora que o projeto do nosso curso foi criado, vamos carregar o
arquivo baixado no servidor onde o RStudio está instalado. Crie uma
pasta chamada dados e salve o arquivo do Tesouro Direto
dentro dela.
Como boa prática, é costume que apenas os códigos sejam carregados no
Github. Para ignorar a pasta de dados, abra o arquivo
.gitignore (caso que não tenha sido criado junto com o
projeto, basta criar um arquivo de texto com esse nome) e adicione uma
linha com a informação /dados.
É possível também fazer o download dos arquivos diretamente pelo R seguindo os passos abaixo.
# Criar um novo diretório
#dir.create("dados")
url <- "https://www.tesourotransparente.gov.br/ckan/dataset/4d4dac3b-96d2-4011-92c9-ddf7d8392622/resource/650cdc18-0513-4bb1-9222-003ad1c11ac7/download/EstoqueTesouroDireto.csv"
td <- "./dados"
# Fazer o download do csv
download.file(url, paste(td,"EstoqueTesouroDireto.csv",sep = "/"),
mode="wb")
Feito isso, vamos agora carregar os dados no R de diferentes métodos.
Método point-and-click
Para isso, clique em Import Dataset, no atalho do painel
Environment, na opção From Text(readr). Temos
duas opções: informar o local do arquivo que você baixou ou o link onde
ele está hospedado. No nosso caso, é o mesmo endereço em que baixamos os
dados do estoque
do Tesouro Direto, usando o arquivo .csv.
Vamos informar o link, para tornar o processo mais rápido.
Assim que você inserir o link para a pesquisa, clique em
Update para visualizar uma prévia dos dados. Mude o
delimitador dos dados para Semicolon, clique em
Configure no campo Locale e altere o marcador
decimal para “,” (Decimal Mark), deixando vazio o campo
Grouping Mark. Aceite as configuração realizadas clicando
em Configure e, finalmente, clique em Import.
Repare que o comando necessário para carregar os dados aparece no
console. A função utilizada para ler o conjunto de dados foi
read_delim, do pacote `readr``. Copie e rode essa linha de
comando diretamente no console, para ver como carregar a base sem o
auxílio do painel.
library(readr)
EstoqueTesouroDireto <- read_delim("https://www.tesourotransparente.gov.br/ckan/dataset/4d4dac3b-96d2-4011-92c9-ddf7d8392622/resource/650cdc18-0513-4bb1-9222-003ad1c11ac7/download/EstoqueTesouroDireto.csv",
delim = ";", escape_double = FALSE, locale = locale(decimal_mark = ","),
trim_ws = TRUE)
Você poderia carregar os dados, de ambas as maneiras, diretamente
pela linha de comando, de outras formas. Um outro pacote, bastante útil
e veloz para o carregamento de dados, é o data.table. Vamos
treinar o carregamento dos dados pela linha de comando com ele. Para
isso, vamos antes limpar o ambiente, excluindo os objetos carregados
anteriormente, com a função rm().
rm(EstoqueTesouroDireto) # Remove apenas o objeto "EstoqueTesouroDireto"
rm(list=ls()) # Remove todos os objetos do ambiente
Note que você pode excluir todos os objetos do ambiente, listando-os
com a função ls(). Contudo, os arquivos excluídos serão
somente aqueles carregados no âmbiente global. Muitas vezes, objetos
carregados em outros ambientes podem continuar carregados, consumindo a
memória do computador. Utilize a função gc() para fazer uma
limpeza na memória.
gc()
Mesmo com esses dois procedimentos, o R não fica completamente
“limpo”. Por exemplo, todos os pacotes carregados na sessão permanecem
prontos para uso, também consumindo memória. Para eliminar todos os
objetos de todos os ambientes, será recessário iniciar uma nova sessão
Para fazer isso, você pode clicar no botão vermelho do canto superior
direito (liga/desliga) ou utilizar o atalho de teclado
crtl+shift+F10.
Vamos também definir o diretório padrão em que estamos trabalhando. O
RStudio server, por padrão, utilizará a pasta do seu usuário no
servidor. Para consultar o diretório ativo no momento, utilize a função
getwd().
getwd() # Consultar diretório de trabalho ativo
Vamos alterar para a pasta dados, criada para armazenar
as bases de dados.
# Alterar diretório para 'dados'
setwd("./dados")
# Visualizar diretório ativo
getwd()
# Listar arquivos
list.files()
# Retornar para o nível anterior do diretório
setwd("..")
# Consultar diretório
getwd()
Repare que existem várias maneiras de definir o diretório padrão.
Caso ele seja um subdiretório do qual você já está trabalhando
atualmente, basta entrar com o caractere . antes do caminho
desejado. Este recurso é um atalho para o endereço do diretório
atualmente ativo no R. Você também pode indicar o caminho completo.
Atente-se para o fato de que o padrão dos caminhos é a barra invertida
/. Apesar de este ser o padrão Linux, ele também deve ser
seguido nas demais plataformas, como o Windows (você pode utilizar
também duas barras seguidas nos caminhos do Windows \\). Um
atalho para o diretório padrão do seu R é o caractere ~. O
caractere .. indica o nível anterior do diretório.
Método por linha de comando
Agora vamos carregar novamente a base do Tesouro Direto, desta vez apenas utilizando a linha de comando.
# Carregar o pacote
library(data.table)
# Carregar a base de um link da internet.
EstoqueTesouroDireto <- data.table::fread("https://www.tesourotransparente.gov.br/ckan/dataset/4d4dac3b-96d2-4011-92c9-ddf7d8392622/resource/650cdc18-0513-4bb1-9222-003ad1c11ac7/download/EstoqueTesouroDireto.csv",dec = ",",encoding = "Latin-1",
data.table = FALSE,
integer64 = "character")
# Carregar a base de um arquivo local
EstoqueTesouroDireto <- data.table::fread("dados/EstoqueTesouroDireto.csv",
dec = ",",encoding = "Latin-1",
data.table = FALSE,
integer64 = "character")
Com a função fread() é possível carregar a base de ambas
as maneiras vistas anteriormente. Note que a função fread()
detectou o delimitador automaticamente. Informamos apenas que o
separador decimal da nossa base é a vírgula, com a opção
dec="," e que o enconding do arquivo é
enconding=Latin-1. Essa última opção é importante quando
estamos transitando arquivos salvos em diferentes plataformas,
principalmente entre Windows e Linux, que possuem formas distintas de
tratar caracteres especiais. O parâmetro data.table=FALSE
carregará a tabela no formato data.frame, ao invés do
padrão data.table, enquanto o parâmetro
integer64 = "character" irá tratar número do tipo
Bigint como character. Neste curso, aprenderemos a
trabalhar data.frames e tibbles, embora exista
a possibilidade de se realizar manipulações com o pacote
data.table de maneira bastante eficiente.
Carga pelo banco de dados
Para isso, vamos precisar do pacote DBI, que fará a
nossa conexão com o banco de dados. Isso é feito através da função
dbConnect().
O primeiro argumento é o driver necessário para realizar a conexão,
fornecido pelo pacote odbc. O segundo argumento desta
função é o nome da conexão, atribuída no momento da configuração da
conexão ODBC. No RServer, o nome atribuído foi comeq. Este
argumento deve ser fornecido entre aspas. Os próximos argumentos são o
nome de usuário e senha. Você deve usar as suas credenciais, fornecidas
pelo administrador do banco de dados.
# Carregar pacotes
library(DBI)
library(odbc)
# Abrir conexão com o banco de dados
# Atenção! Não utilize a função Sys.getenv sem confirar o ambiente antes!
db <- DBI::dbConnect(odbc::odbc(),
"comeq",
uid=Sys.getenv("matricula"),
pwd=Sys.getenv("senha"))
Pronto! Já estamos conectados ao banco de dados.
IMPORTANTE: sempre que você estiver escrevendo um código, o qual irá
posteriormente subir no Github/Gitlab, NUNCA, JAMAIS e EM HIPÓTESE
ALGUMA salve seu usuário e senha no script. Isto representa uma grave
quebra de segurança, podendo ter importantes repercussões. Utilize umas
das três opções: i) sempre preencha manualmente seu usuário e senha;
utilize o arquivo .Renviron com suas credenciais (APENAS EM
MÁQUINAS PRIVADAS); utilize o pacote keyring para o
gerenciamento de credenciais. A solução acima utiliza o arquivo
.Renviron, que pode ser configurada pelo RStudio com a
função usethis::edit_r_environ().
Assim que você fizer a conexão, o pacote já ativa a aba
Connections, no painel superior direito.
Por ali, você pode consultar os bancos, esquemas e tabelas disponíveis, bem como as colunas. Para verificar uma prévia com as 1.000 primeiras linhas, basta clicar no ícone da tabela desejada. Para consultar as tabelas ou colunas disponíveis (que são retornadas em formato de vetor), utilize as funções abaixo. O argumento destas funções é o objeto com a conexão que fizemos para o banco de dados.
DBI::dbListTables(db) # Consultar tabelas
DBI::dbListFields(db,Id(schema="pnadc",
table="pnadt202301")) # Consultar colunas da tabela pnadt202301
Feito isso, já estamos pronto para carregar uma base no R. Para isso,
vamos utilizar a função dbGetQuery. Dentro dessa função,
enviamos uma consulta SQL ao banco de dados, da mesma maneira que
fazemos em qualquer outro programa de acesso a BD. A única diferença é
que o pacote DBI estará intermediando a comunicação,
apresentando os dados quando pertinente. Por exemplo, caso tenhamos
permissão para tal, podemos criar, excluir ou alterar tabelas do banco
de dados diretamente do R.
Vamos, então, carregar a pnadc trimestral mais recente. A estrutura
para realizar uma consulta é bastante simples: dizemos a ação que
queremos realizar que, no caso da consulta, é feita com a palavra
select; informamos as variáveis a serem carregadas,
separando-as por vírgulas; dizemos de onde queremos obter esses dados,
com a palavra from; e informamos o local em que a tabela
está armazenada no banco de dados, na estrutura “esquema.tabela”, no
nosso caso, pnadc.pnadt202301.
Como consultamos os nomes das tabelas anteriormente, vamos carregar somente as informações sobre a UF,o peso do morador/domicílio (variável “V1028”), a situação do domicílio (“V1022”) e o rendimento do trabalho (“VD4020”), para realizarmos um pequeno exercício.
# Carregar a base de moradores da PNADC
pnadc <- DBI::dbGetQuery(db,'select "UF","V1028","V1022","VD4020" from pnadc.pnadt202301')
No objeto pnadc, podemos consultar das informações
carregadas. Você pode clicar no objeto carregado ou utilizar a função
View(), utilizando o nome do objeto como argumento. Para
consultar a classe do objeto carregado, utilize a função
class(), enquanto, para ver os nomes da colunas, utilize as
função names(). A função head() apresenta as
primeiras linhas do data.frame, enquanto a função tails()
apresenta as últimas. Os tipos das colunas podem ser consultados com a
função str() ou glimpse(), do pacote
dplyr. Finalmente, podemos consultar a quantidade de linhas
e a quantidade de colunas carregadas com as funções nrow()
e ncol(), respectivamente.
#View(pnadc) # Visualizar o objeto pnadc
class(pnadc) # Verificar a classe do objeto
names(pnadc) # Verificar o nome das colunas carregadas
head(pnadc) # Verificar as primeiras linhas da tabela
tail(pnadc) # Verificar as últimas linhas da tabela
str(pnadc) # Verificar as classes das colunas
dplyr::glimpse(pnadc) # Outra opção para checar as classes
nrow(pnadc) # Consultar o número de linhas
ncol(pnadc) # Consultar o número de colunas
O objeto do tipo data.frame, que é o formato do objeto
pnadc, será o foco da nossa aula. Esse objeto é como se fosse
uma matriz, em que as linhas representam as observações e as colunas as
variáveis. Como em uma matriz, você pode acessar as linhas e as colunas
com o operador [,] logo após o nome do objeto. À esquerda,
indica-se a posição da linha, enquanto, à direita, indica-se a coluna.
Você pode utilizar a posição numérica ou o nome da coluna. Repare que a
função names() indica, além dos nomes, a posição das
colunas. Elas ficam entre colchetes, apresentadas em ordem crescente.
Outra maneira para acessar uma variável específica é utilizando o
caractere $ logo após o nome do data.frame.
Por exemplo, para consultar apenas a coluna com os esquemas, utilize um
dos comandos abaixo.
pnadc$UF # Consultar apenas a coluna "UF"
pnadc[,1] # Outra maneira de consultar a coluna "UF"
pnadc[,"UF"] # Mais uma maneira de consultar a coluna "UF"
pnadc[1:2,1:2] # Selecionar apenas as duas primeiras linhas e colunas
pnadc[1:2,]$UF # Selecionar apenas as duas primeiras linhas da coluna "UF"
pnadc[c(1,7,10:12),c(1,3)] # Selecionar linhar e colunas distintas
Para fazer uma tabulação simples, de modo a verificar o número
amostrado em cada UF, utilize a função table().
table(pnadc$UF) # Tabular a coluna
table(pnadc[,1]) # Tabular a coluna
table(pnadc[,"UF"]) # Tabular a coluna
Agora vamos aprender a filtrar os dados. Em outras palavras, queremos olhar apenas as linhas com uma dada característica. Isso pode ser feito da seguinte maneira.
pnadc[pnadc$UF==53,3]
pnadc[pnadc[,1]==53,]$V1022
Dentro da tabela, para indicar a linha a ser selecionada, informamos
que queremos apenas as linhas em que a coluna UF é
exatamente igual a 53. Se este fosse um campo caractere, deveríamos
colocar a condição do filtro entre aspas (duplas ou simples, no R é
indiferente).
Vamos refazer todos esses passos, agora de uma maneira muito mais
simples e rápida, com o pacote dplyr, utilizando os
pipes.
# Carregar o pacote dplyr
library(dplyr)
# Consultar as tabelas disponíveis
pnadc %>%
# Filtrar apenas linhas da uF 53
dplyr::filter(UF=="53") %>%
# Selecionar apenas as colunas UF eV1022
dplyr::select(UF,V1022) %>%
# Olhar apenas as primeiras linhas
head()
Com as funções filter e select, conseguimos
filtrar e selecionar colunas facilmente, de uma maneira rápida e
elegante.
Perceba que foi necessário o conhecimento prévio de que o valor
53 estava presente na coluna UF. O pacote
stringr conta com uma função para identificar certos
argumentos no filtro, baseado em caracteres. Vejamos a função
str_detect().
# Consultar as linhas disponíveis
pnadc %>%
# Filtrar apenas linhas do esquema PDAD
dplyr::filter(stringr::str_detect(UF, pattern = "5")) %>%
# Selecionar apenas a coluna UF
dplyr::pull(UF) %>%
# tabular os dados
table()
Assim, podemos detectar facilmente um tipo de argumento quando não temos certeza do valor exato ou quando as possibilidades de categorias são muito amplas.
Muitas vezes precisamos alterar o nome de uma coluna, seja para
tornar seu entendimento mais fácil, seja por questão de conveniência,
seja por necessidade. Podemos fazer isso de duas maneiras: com a função
colnames(), do pacote base, ou com a função
rename(), do pacote dplyr.
# Alterar o nome da coluna "V1022" para Peso
colnames(pnadc)[2] <- "Peso"
names(pnadc)[2] <- "Peso"
# Verificar o resultado
names(pnadc)
# Alterar o nome com o dplyr
pnadc %>%
# Alterar os nomes das colunas
dplyr::rename(Area=V1022,
V1028=Peso) %>%
# Verificar resultado com as primeiras linhas
head()
# Retornar a variável de peso para o nome original
pnadc <- pnadc %>%
# Alterar o nome da coluna
dplyr::rename(V1028=Peso)
Outras manipulações de dados
Note que os dados são apresentados com suas codificações. Precisaremos do dicionário de variáveis para entendermos a correspondências entre os códigos e as UFs.
Para termos o dicionário de dados da base de moradores prontamente
acessível dentro do R, vamos carregá-lo utilizando a função
readxl::read_excel().
# Definir url
url <- "https://ftp.ibge.gov.br/Trabalho_e_Rendimento/Pesquisa_Nacional_por_Amostra_de_Domicilios_continua/Trimestral/Microdados/Documentacao/Dicionario_e_input_20221031.zip"
# Baixar arquivo
download.file(url,
destfile = "./dados/dic.zip",
mode = "wb")
# Extrair informações
unzip("./dados/dic.zip",
exdir = "./dados")
# Listar os arquivos do diretório dados
list.files("dados")
# Carregar as informações do dicionário
dic <- readxl::read_excel("dados/dicionario_PNADC_microdados_trimestral.xls",
skip = 2,
sheet = 1) %>%
# Preenchers os NAs com os valores antecessores
dplyr::mutate_at(vars(3,5),
list(~zoo::na.locf(.,na.rm=F))) %>%
# Selecionar colunas de interesse
dplyr::select(3,5:7) %>%
# Eliminar linha com NA
dplyr::filter(is.na(`descrição`)==F) %>%
# Renomear colunas
dplyr::rename_all(list(~c("VAR","DESC_VAR",
"VALOR","DESC_VALOR")))
Vamos agora ver como criar uma nova variável, no formato fator,
atribuindo label (rótulo) aos valores. Faremos isso com as UFs
de residência dos respondentes. Isso pode ser feito, dentro do pacote
dplyr, com as funções mutate ou
transmute. A primeira cria uma nova variável no banco de
dados, mantendo todas as demais, enquanto a segunda mantém somente as
variáveis que estão sendo criadas dentro da função.
# Construir uma variável em formato de fator
UF <- pnadc %>%
dplyr::transmute(UF=factor(UF,
levels=c(11:17,
21:29,
31:33,35,
41:43,
50:53),
labels=c('Rondônia',
'Acre',
'Amazonas',
'Roraima',
'Pará',
'Amapá',
'Tocantins',
'Maranhão',
'Piauí',
'Ceará',
'Rio Grande do Norte',
'Paraíba',
'Pernambuco',
'Alagoas',
'Sergipe',
'Bahia',
'Minas Gerais',
'Espírito Santo',
'Rio de Janeiro',
'São Paulo',
'Paraná',
'Santa Catarina',
'Rio Grande do Sul',
'Mato Grosso do Sul',
'Mato Grosso',
'Goiás',
'Distrito Federal')))
# Tabular os resultados
table(UF$UF)
Atente-se que o nome UF está sendo utilizado para designar
um objeto e uma coluna dentro de um data.frame. Não há
problema nenhum nisso, basta apenas se atentar para a diferença do que
se está utilizando ao realizar sua programação.
A função fator possui três argumentos principais: o vetor a ser “fatorizado”, os níveis existentes, i.e., o conjunto de valores únicos existente no vetor, e os rótulos que cada um dos níveis deve receber.
Poderíamos ter feito isso utilizando diretamente o dicionário de variáveis, ajustando as informações correspondentes.
# Recodificar os nomes
uf_codificada <- pnadc %>%
dplyr::transmute(uf=factor(UF,
levels = dic[dic$VAR=="UF",]$VALOR,
labels = dic[dic$VAR=="UF",]$DESC_VALOR))
# Tabular os resultados
table(uf_codificada$uf)
Apesar de parecer mais complexo, isso evita que tenhamos de copiar, colar ou escrever manualmente o nome de todas as 27 unidades da federação. Se o número de categorias fosse mais elevado, certamente esses passos seriam fundamentais para dar agilidade à tarefa a ser realizada.
Agora que já conseguimos identificar qual foi a amostra em cada uma
das UFs, vamos fazer um gráfico simples, para verificarmos onde
obtivemos as maiores amostras. Para isso, vamos usar a o pacote
ggplot.
O ggplot trabalha com data.frames, e não somente com
vetores individuais, como é o caso da função plot,
disponível no pacote graphics do R. Uma vantagem do
ggplot é que você pode adicionar camadas a um gráfico
existente de maneira simples e rápida, com o operador +. A
função aes() é utilizada para especificar quais serão os
eixos do gráfico, usualmente x e y, bem como o que deverá ser desenhado
no gráfico. Para um tutorial mais completo, acesse esse
site.
UF %>%
# Criar a área de plotagem, com o eixo X
ggplot(aes(x=UF)) +
# Inserir a geometria do tipo "Barra", com a opção de contagem (gerada automaticamente no eixo y)
geom_bar(stat = "count") +
# Inverter os eixos
coord_flip()
Agora vamos organizar essas informações de uma outra maneira,
resumindo o total da amostra por UF, refazendo o gráfico, para colocá-lo
em ordem decrescente do n amostrada. Para isso, vamos utilizar o pacote
forcats.
# Contar quantas pessoas foram amostradas em cada UF
UF %>%
# Contar quantas observações temos em cada UF
dplyr::count(UF) %>%
# Plotar o gráfico, ajustando as categorias de acordo com o total amostrado
ggplot(aes(x=forcats::fct_reorder(UF,n),y=n)) +
# Desenhar a geometria de barras
geom_bar(stat = "identity") +
# Inverter os eixos
coord_flip() +
# Rotular os eixos
labs(y="Amostra",
x="UF")
Agora, a apresentação da informação ficou um pouco mais clara. Com o
pacote ggplot, é possível alterar praticamente todos os
aspectos de um gráfico. Existem alguns pacotes que carregam temas
pré-configurados para serem utilizados com o ggplot. Vamos
testar o pacote ggthemes. Basta rodar a função e adiciconar
um tema ao final da função. Vamos também mudar a cor das barras com o
argumento “fill” dentro da função
geom_bar(). Você pode informar cores com seus respectivos
nomes (em inglês) ou com códigos hexadecimais das cores (por exemplo
“#12660f”).
library(ggthemes)
# Contar quantas pessoas foram amostradas em cada UF
UF %>%
# Contar quantas observações temos em cada UF
dplyr::count(UF) %>%
# Plotar o gráfico, ajustando as categorias de acordo com o total amostrado
ggplot(aes(x=forcats::fct_reorder(UF,n),y=n)) +
# Desenhar a geometria de barras
geom_bar(stat = "identity",fill="#12660f") +
# Inverter os eixos
coord_flip() +
# Rotular os eixos
labs(y="Amostra",
x="UF") +
# Adicionar o tema
theme_minimal()
Posteriormente, vamos aprender a realizar outras configurações nos
gráficos gerados com o ggplot.
Aprofundando o tratamento de strings
Manipular string pode ser muito importante em uma pesquisa. Vamos ver
como podemos detectar algumas expressões com o pacote
stringr.
Abaixo você encontra alguns exemplos de operadores ao utilizar strings:
- ‘can’: reconhece tudo que tenha “can”, ignorando maiúsculas
- ‘CAN’: reconhece tudo que tenha “CAN”, ignorando minúsculas
- ‘can$’: reconhece apenas o que termina exatamente em “can”
- ‘^can’: reconhece apenas o que começa exatamente com “can”
- ‘c ?an’: reconhece tudo que tenha “can”, com ou sem espaço entre o “c” e o “a”
Veja como funcionam os testes lógicos.
| strings | ^can | c ?an | can | CAN | can$ |
|---|---|---|---|---|---|
| bacana | FALSE | TRUE | TRUE | FALSE | FALSE |
| can | TRUE | TRUE | TRUE | FALSE | TRUE |
| CANA | FALSE | FALSE | FALSE | TRUE | FALSE |
| encanado | FALSE | TRUE | TRUE | FALSE | FALSE |
| encanta | FALSE | TRUE | TRUE | FALSE | FALSE |
| levou o cano | FALSE | TRUE | TRUE | FALSE | FALSE |
Para se verificar quantas vezes um caractere se repete, dado um
determinado padrão, utilizamos os símbolos +,
* e {x,y}.
ey+significaee depoisy“uma vez ou mais”. Por exemplo, reconhecehey,heyy,a eyyy, mas não reconhecee,ynemyy.ey*significa “nenhuma vez ou mais”. Por exemplo, reconhecehey,heyy,a eyyyee, mas não reconheceynemyy.ey{3}significa “exatamente três vezes”. Por exemplo, reconheceeyyyeeyyyy, mas não reconheceeyy.ey{1,3}significa “entre uma e três vezes”.
Para aplicar um quantificador a um conjunto de caracteres, usamos os
parênteses. Por exemplo, (ey )+ reconhece
ey ey.
Colocando caracteres dentro de [], reconhecemos
quaisquer caracteres desse conjunto. Por exemplo:
[Cc]ursopara reconhecer “curso” em maiúsculo ou minúsculo.[0-9]para reconhecer somente números. Para letras:[a-z],[A-Z],[a-zA-Z]- O símbolo
^dentro do colchete indica negação. Por exemplo,[^0-9]significa todos os caracteres, exceto números. - O símbolo
.fora do colchete indica “qualquer caractere”. Dentro do colchete é apenas um caractere - Com
[[:space:]]reconhecemos espaços, com[[:blank:]]reconhecemos espaços em branco e tabulações, com[[:lower:]]reconhecemos minúsculas, com[[:upper:]]reconhecemos minúsculas e com[[:punct:]]+reconhecemos pontuações.
Trabalhando com datas
Vez ou outra nos deparamos com bases de dados que contêm variáveis do
tipo data. Dentro da família tidyverse, temos o pacote
lubridate, que facilita muito a manipulação deste tipo de
dado. Na base com estoque do tesouro direto, temos a variável
Vencimento do Titulo, que traz o dia de vencimento de cada
título, e a variável Mes Estoque, que traz a informação do
título naquela referência. Vamos utilizar essas variáveís para manipular
datas.
Vamos verificar como estão preenchidas as primeiras linhas dessas
colunas, com auxílio da função head().
# Verificar as primeiras informações da coluna
head(EstoqueTesouroDireto$`Vencimento do Titulo`)
head(EstoqueTesouroDireto$`Mes Estoque`)
Repare que a primeira data está no formato “DD/MM/YYYY”, enquanto a segunda está no formato “MM/YYYY”.
Vamos analisar agora qual a classe dessas colunas.
# Verificar a classe das colunas
class(EstoqueTesouroDireto$`Vencimento do Titulo`)
class(EstoqueTesouroDireto$`Mes Estoque`)
Vemos que elas são da classe “character”. Precisamos alterar o formato delas para fazermos cálculos de tempo. Faremos isso e calcularemos o valor do estoque de um título específico.
# Carregar pacote lubridate
library(lubridate)
# Utilizar a base de domicílios
datas_tesouro_ipca <- EstoqueTesouroDireto %>%
# Filtrar para um título específico
dplyr::filter(`Tipo Titulo`=="Tesouro IPCA+") %>%
# Selecionar a data da pesquisa
dplyr::select(`Tipo Titulo`,`Vencimento do Titulo`,`Mes Estoque`,PU,`Valor Estoque`) %>%
# Transformar o campo de data (em caracter) em data (formato data)
dplyr::mutate(`Vencimento do Titulo`=lubridate::dmy(`Vencimento do Titulo`),
`Mes Estoque`=lubridate::dmy(paste0("01",`Mes Estoque`))) %>%
# Filtrar para títulos já vencidos
dplyr::filter(`Vencimento do Titulo`<Sys.Date())
# Verificar datas com títulos já vencidos
table(datas_tesouro_ipca$`Vencimento do Titulo`)
Assim, temos a informação de que dois títulos do tipo Tesouro IPCA+ já tiveram vencimento no passado, nas datas de 15/05/2015 e 15/05/2019.
Gravar uma tabela no formato “.csv”
Agora que geramos a tabela com as informações filtradas, vamos salvar
os resultados em um arquivo .csv. Para isso, vamos utilizar
a função write.table(), do pacote utils. Com a
função, informe o objeto que você quer utilizar para gerar o arquivo no
primeiro argumento e o nome do arquivo a ser gerado no segundo
argumento. O arquivo será salvo no seu diretório de trabalho, por
padrão. Caso você queria salvá-lo em outro local, basta informar o
caminho desejado antes do nome do arquivo (e.g. dados/,
para salvar em um subdiretório chamado dados).
Assim como as colunas possuem nomes, as linhas também podem ser
nomeadas no R. Quando não damos um nome específico para as linhas, elas
são, por padrão, nomeadas com números inteiros sequenciais, de 1 até o
número de linhas da tabela. Consulte essa informação com a função
row.names().
Como não queremos que essas informações apareçam na nossa tabela,
utilizamos o argumento row.names = F no momento de
escrevermos a tabela. Além disso, o arquivo será gerado, por padrão,
delimitado por espaços. Vamos alterar o delimitador para ponto e vírgula
;. Poderíamos escolher qualquer outro delimitador desejado.
Por fim, caso necessário, você também pode informar o
encoding desejado para salvar o arquivo, com o
parâmtero fileEncoding. Se o seu objeto tiver algum valor
ausente, você pode alterar o formato que ele será gravado com o
parâmetro na. Por exemplo, para que os valores ausentes
sejam gravados sem informação, utilize na="". Caso você
queira que as colunas com string sejam gravadas entre aspas, utilize o
parâmetro quote=TRUE.
write.table(datas_tesouro_ipca,
"dados/tesouro_ipca.csv",
row.names = F, sep = ";",
fileEncoding = "latin1")
Vamos verificar o resultado localmente. Procure no diretório o arquivo que acabou de ser criado e abra-o. Assim, você pode compartilhar esse resultado com outros pesquisadores em um formato legível em outros softwares, como o Microsoft Excel.
Para gravar diretamente em um arquivo do tipo .xlsx,
podemos utilizar a função xlsx::write.xlsx. Vejamos um
exemplo abaixo.
# Carregar o pacote
library(xlsx)
# Salvar as informações
xlsx::write.xlsx(datas_tesouro_ipca,
file = "dados/tesouro_ipca.xlsx",
sheetName = "tesouro IPCA",
row.names = F)
Atualmente, o pacote grava apenas objetos do tipo
data.frame. Lembre-se de converter o objeto do tipo
tibble para data.frame antes de salvar, caso
você esteja trabalhando com este tipo de informação.
Operações com datas
Vamos agora aprender a fazer operações com datas. Vamos calcular o intervalo existente entre a data de vencimento dos títulos e a data de hoje.
# Criar um objeto com a data de referência desejada
ref <- Sys.Date()
# Armazenar o resultado em um objeto
datas_tesouro_ipca <-
# Utilizar a base de domicílios
datas_tesouro_ipca %>%
# Transformar o campo de data (em caracter) em data (formato data)
dplyr::mutate(# Calcular a diferença entre as datas, em meses
dif_data_mes=interval(`Vencimento do Titulo`,ref) %/% months(1),
# Calcular a diferença entre as datas, em dias
dif_data_dia=interval(`Vencimento do Titulo`,ref) %/% days(1))
# Ver resultado
table(datas_tesouro_ipca$dif_data_mes)
# Ver resultado
table(datas_tesouro_ipca$dif_data_dia)
Vamos aproveitar para fazer um gráfico com a evolução do preço unitário de um desses títulos.
# Utilizar o objeto de referências
datas_tesouro_ipca %>%
# Filtrar para o título de uma data espefífica
dplyr::filter(`Vencimento do Titulo`==dmy("15/05/2015")) %>%
# Criar um plot com a diferença de dias no eixo x
ggplot(aes(x=`Mes Estoque`,y=`Valor Estoque`/1000000000)) +
# Fazer o gráfico de densidade
geom_line() +
# Adicionar uma linha vermelha vertical no ponto zero
geom_vline(aes(xintercept= dmy("01/01/2013")), color="red")+
# Nomear os eixos
labs(y="Valor do estoque",
x="Data")
Assim, percebemos que, até 2013, houve aumento constante do valor do estoque, a partir de quando há uma queda antes de uma recuperação antes do vencimento.
Criando mapas
Com o R, é possível fazermos mapas com relativa facilidade. Para tanto, precisaremos de informações geográficas dos mapas que queremos desenhar. Vamos fazer conexão com o banco de dados a e pegar as informações necessárias.
# Carregar pacotes
library(ggrepel)
library(sf)
# Fazer a conexão no banco do NUGEO
db <- DBI::dbConnect(odbc::odbc(),
"comeq",
user=Sys.getenv("matricula"),
password = Sys.getenv("senha"),
maxvarcharsize=0 # Parâmetro necessário para não retornar erro na consulta
)
# Puxar as informações de geometria
UF <- sf::st_read(db, query="SELECT * FROM ibge.geo_uf",
geometry_column = "geometry")
# Calcular os totais populacionais com base na PNADC
pop <- pnadc %>%
# Agrupar por RA
dplyr::group_by(UF) %>%
# Somar os fatores
dplyr::summarise(n=sum(V1028)) %>%
# Ajustar tipo da coluna para o join
dplyr::mutate(UF=as.character(UF))
Neste momento, temos dois objetos com as informações que queremos trabalhar: um com as informações geográficas das UFs e outro com as informações populacionais. Para fazer o mapa, precisamos juntar essas informações. Para tanto, utilizaremos as funções de junção.
Para o nosso exemplo, vamos utilizar a função
left_join() do pacote dplyr. A junção de bases
pode ser feita sob várias perspectivas. Veja a figura abaixo (extraída
desse
site).
Conforme apresentado no diagrama de Venn, temos junções à
esquerda, à direita, intersecções e complementares de conjuntos. De
maneira simples, a nossa intenção é relacionar conjuntos baseado em uma
característica comum entre eles – a chave (ou chaves) de ligação. No
nosso caso, o código que identifica cada UF é dado pela coluna
UF na PNADc e a coluna CD_UF na base
terrotorial.
# Juntar as informações
mapa <- UF %>%
# Fazer um join das informações populacionais
dplyr::left_join(pop,by=c("CD_UF"="UF"))
Consulte o número de linhas e colunas da base criada. Repare que o
número de linhas permaneceu o mesmo da base posicionada à esquerda,
i.e., base territorial “UF”. Como não havia nenhuma repetição nessa
base, o resultado já era esperado. Experimente rodar o código novamente,
agora substituindo a função left_join por
right_join e perceba que o resultado é exatamente o mesmo.
Esse é um cuidado que se deve ter quando o desejo é ligar duas bases.
Caso as chaves de ligação tivessem múltiplos casos, a função iria
realizar as combinações pertinentes, o que, geralmente, causa um grande
aumento no tamanho da base. Dependendo da situação, tal operação pode
travar sua sessão no RStudio server (além de travar o servidor como um
todo) ou, em um banco de dados, igualmente travá-lo.
Caso as duas bases tivessem colunas de mesmo nome, não seria
necessário informar o argumento by. A função identifica
todas as colunas de nomes iguais e tenta fazer a junção por todas essas
colunas. Se houvesse mais de uma condição, bastaria adicioná-las à
direita, separando-as por vírgulas
(e.g. by=c("UF"="CD_UF","MUN"="CD_MUN")).
Atenção: para que o join seja realizado, o tipo da variável
deve ser o mesmo. Por exemplo, se a chave de identificação for do tipo
integer em uma base e do tipo numeric na
outra, o join não será realizado. O mesmo vale para
chaves do tipo character e integer ou
numeric.
Vamos, agora, finalizar a construção do nosso mapa.
map <- mapa %>%
# Calcular o centro das coordenadas (para o label)
dplyr::mutate(lat=sf::st_coordinates(sf::st_centroid(geometry))[,2],
long=sf::st_coordinates(sf::st_centroid(geometry))[,1]) %>%
# Plotar o mapa
ggplot()+
# Fazer um mapa coroplético com a população
geom_sf(aes(fill = n)) +
# Mudar a escala de cores
scale_fill_distiller(palette="Blues",
name="População",
labels= scales::unit_format(unit = "Mil", scale = 1e-3),
direction = 1) +
# Tirar o sistema cartesiano
theme(panel.grid = element_line(colour = "transparent"),
panel.background = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
legend.title = element_text(size = 14),
legend.text = element_text(size = 12)) +
# Adicionar os labels
geom_label_repel(aes(long,lat,label = NM_UF),
size=5, fontface="bold", family="Arial",
label.padding=unit(0.10,"line")) +
# Retirar o label dos eixos
labs(x="",y="")
# Salvar o mapa criado
ggsave(map,filename = "figuras/mapa_pop.png",
bg = "transparent",
width = 30,
height = 18,
units = "cm")
Caso você queira criar um mapa com um shape que não está disponível no banco de dados, utilize os passos abaixo. No exemplo abaixo, estamos baixando o mesmo shape diretamente do site do IBGE.
# Carregar pacotes
library(ggrepel)
library(sf)
# Link para o arquivo shape
tf <- "https://geoftp.ibge.gov.br/organizacao_do_territorio/malhas_territoriais/malhas_municipais/municipio_2022/Brasil/BR/BR_UF_2022.zip"
# Caminho para salvar o arquivo
td <- "dados/ufs.zip"
# Fazer o download do arquivo
download.file(tf, td, mode="wb")
# Descompactar o arquivo
unzip(td,exdir="dados/ufs")
# Carregar o arquivo .shp
mapa <- sf::st_read("dados/ufs")
# Calcular o total de moradores por UF
mor <- pnadc %>%
# Agrupar por RA
dplyr::group_by(UF) %>%
# Somar os fatores
dplyr::summarise(n=sum(V1028)) %>%
# Ajustar tipo da coluna para o join
dplyr::mutate(UF=as.character(UF))
# Criar um objeto com os centros dos polígonos
pontos <- mapa %>%
sf::st_centroid() %>%
dplyr::mutate(lat=sf::st_coordinates(.)[,1],
long=sf::st_coordinates(.)[,2]) %>%
dplyr::select(CD_UF,lat,long) %>%
sf::st_set_geometry(NULL)
# Fazer o mapa
map <- mapa %>%
dplyr::left_join(mor,by=c("CD_UF"="UF")) %>%
dplyr::left_join(pontos) %>%
ggplot()+
geom_sf(aes(fill = n)) +
# Mudar a escala de cores
scale_fill_distiller(palette="Blues",
name="População",
labels= scales::unit_format(unit = "Mil", scale = 1e-3),
direction = 1) +
# Retirar o sistema cartesiano
theme(panel.grid = element_line(colour = "transparent"),
panel.background = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
legend.title = element_text(size = 14),
legend.text = element_text(size = 12)) +
geom_label_repel(aes(lat, long, label = NM_UF),size=3, fontface="bold", family="Arial",
label.padding=unit(0.10,"line")) +
labs(x="",y="")
# ggsave(map,filename = "figuras/mapa_pop.png",
# bg = "transparent",
# width = 30,
# height = 18,
# units = "cm")
Atualização de valores monetários
Recorrentemente, precisamos atualizar valores monetários. Para isso,
vamos utilizar o pacote sidrar para coletar os dados de
inflação do Sistema IBGE
de Recuperação Automática - SIDRA. Para fazer isso, vamos montar a
tabela desejada no Sidra para os dados do IPCA, disponível nesse link. Após
selecionar os valores, clique no ícone para compartilhar a tabela e
copie o link da api, a partir do valor /t.
Após baixar os dados, vamos manipular os dados para criar inflatores para a a atualização dos valores monetários.
Vamos aproveitar a base do IPCA para aprendermos uma manipulação
muito importante de bases de dados. Para fazer gráficos, o formato
long é muito útil, enquanto o formato wide
apresenta a tabela no formato de colunas. Vamos treinar estes conceitos
carregando a inflação, de 2020 até a data mais atual, do DF, do Brasil,
de São Paulo e do Rio de Janeiro.
# Carregar informações da inflação para as localidades desejadas
inflacao <- sidrar::get_sidra(api = '/t/7060/n1/all/n7/3301,3501/n6/5300108/v/63/p/all/c315/7169/d/v63%202')
# Gravar a inflação transformada em um objeto
inflacao_wide <- inflacao %>%
# Selecionar as variáveis de interesse
dplyr::select(`Mês (Código)`,`Brasil, Região Metropolitana e Município`,Valor) %>%
# Renomear as variáveis selecionadas anteriormente
dplyr::rename_all(list(~c("referencia","Local","Valor"))) %>%
# Mudar dados para o formato wide.
tidyr::spread(Local,Valor)
Esse formato, em que temos cada coluna um caso, é o chamado formato
wide, cuja função spread “espalha” os dados no
banco. Vamos, agora, voltar os dados para o formato long,
em que cada linha é um caso.
# Criar um objeto com os dados no formato long
inflacao_long <- inflacao_wide %>%
# Passar as colunas de cada localidade para o formato long, criando
# as variáveis "Local" e "Valor" para receberem os dados de inflação
tidyr::gather("Local","Valor",-1)
A função gather() “junta” os valores para colocar cada
caso em uma linha. Vamos agora fazer um gráfico de linhas com essas
informações, plotando a inflação mensal de 2019 para essas
localidades.
inflacao_long %>%
# Ajustar a variável de referência para o formato data,
# utilizando as informações de mês e ano, acrescentando
# o dia primeiro, apenas como referência
dplyr::mutate(referencia=lubridate::dmy(paste("01",
stringr::str_sub(referencia,5,6),
stringr::str_sub(referencia,1,4)))) %>%
# Filtrar para o último ano (de maio a maio)
dplyr::filter(referencia>=lubridate::dmy("01-12-2018")) %>%
# Plotar o gráfico, com a referência no eixo x,
# a inflação no eixo y e a localidade colorindo as linhas
ggplot(aes(x=referencia,y=Valor,colour=Local))+
# Construir as linhas, variando o tipo de linha conforme o local
geom_line(aes(linetype = Local))+
# Adicionar os pontos
geom_point()+
# Ajustar os rótulos dos meses do eixo x, apresentando-os
# a cada dois meses
scale_x_date(date_breaks = "2 month")+
# Ajustar a legenda das cores, atribuindo cores específicas para as linhas
scale_colour_manual(labels=c("Brasil","Distrito Federal",
"Rio de Janeiro","São Paulo"),
values=c("cadetblue4","coral4",
"darkgoldenrod","chartreuse4"))+
# Ajustar a legenda das linhas, combinando com a legenda anterior
scale_linetype_manual(labels=c("Brasil","Distrito Federal",
"Rio de Janeiro","São Paulo"),
values=c(1:4))+
# Ajustar o rótulo dos eixos
labs(y="Inflação mensal",
x="Período")+
# Alterar a posição da legenda
theme(legend.position = "bottom",
axis.text.x = element_text(angle=90))
Vamos deixar um arquivo separado para atualizar posteriormente os valores de rendimento da PNADC.
inflacao_br <- inflacao %>%
dplyr::filter(`Nível Territorial`=="Brasil",
`Mês (Código)`>202303) %>%
# Organizar dados em ordem cronológica decrescente
dplyr::arrange(`Mês (Código)`) %>%
# Calular o inflator, acumulando os índices mensais
dplyr::mutate(inflator=cumprod(Valor/100+1)) %>%
# Selecionar a referência e o inflator calculado
dplyr::select(`Mês (Código)`,inflator) %>%
# Filtrar para última referência
dplyr::filter(`Mês (Código)`==max(`Mês (Código)`)) %>%
# Ficar somente com o valor da inflação
dplyr::pull(inflator)
Baixar dados do IPEADATA diretamente no R
Assim como podemos baixar informações do IBGE diretamente no R, temos
um pacote, o ipeadatar, para baixar informações do IPEA
Data. Para tanto, precisamos, primeiramente, saber as informações que
estão disponíveis para download. Vamos ver abaixo como isso
funciona.
library(ipeadatar)
# Baixar catálogo de bases
dados_ipeadata <- available_series(language = "br")
Com isso, verificamos um amplo conjunto de informações disponível
para download. Para baixar a informação desejada, basta identificar na
coluna code o código da base e informá-la na função
ipeadata.
# Baixar informações da Taxa de câmbio - R$ / US$ - comercial - compra - média
cambio <- ipeadata("BM_ERC")
Manipulação da PNADC com expansão dos resultados
Conforme dito anteriormente, a PNADC é uma pesquisa amostral, desenhada para fornecer mensalmente a situação do mercado de trabalho brasileiro, além da caracterização socioeconômica e demográfica das UFs brasileiras em períodos determinados. Além disso, ela consegue fornecer informações ainda mais específicas para alguns recortes territorias (áreas rurais e urbanas, regiões metropolitanas, capitais, entre outras). Para mais informações sobre o plano amostral da PNADC, acesse esse material.
A imagem abaixo ilustra o conceito de amostragem aplicado à PNADC (imagem extraída do site mathcaptain.com).
Sendo assim, as estimativas fornecidas pela pesquisa estão sujeitas a um erro amostral, o que torna necessária a consideração de seu desenho amostral para seu cálculo. É com essas informações que construímos intervalos de confiança para as estimativas. De maneira simples, queremos fornecer, com algum grau de confiança, qual o verdadeiro valor populacional dada a amostra coletada. A população considerada para a PNADC parte das estimativas populacionais do próprio IBGE, estando sujeita a revisões conforme novas informações se tormar disponíveis (como, por exemplo, com atualizações do Censo).
Neste curso iremos aprender a declarar o plano amostral da PNADC no
R, utilizando o pacote survey. Vamos utilizar também o
pacote srvyr, que roda o pacote survey sob a
lógica do pacote dplyr, para calcular as estimativas.
Declarar o plano amostral da PNADC
Vamos agora declarar o plano amostral da PNADC trimestral. Para isso, vamos precisar de algumas informações básicas:
- O Peso trimestral com correção de não entrevista com calibração pela
projeção de população:
V1028; - O Peso replicado do domicílio e das pessoas:
V1028001aV1028200
Com essas informações, precisamos de apenas um passo para declarar o plano amostral da PNADC.
Obs.: a partir de 2021, o IBGE introduziu uma mudança na expansão da PNADC, que vigorava até então. Passaram a ser consideradas estimativas populacionais por faixas etárias e sexo. Anteriormente, as estimativas populacionais não contavam com esse detalhamento. Para mais informações, acesse a nota técnica 04/2021 do IBGE e este site e este site para sua aplicação do R.
# Carregar pacote
library(srvyr)
# Definir as variáveis para download
vars <- c("UF","V1028","V1022","VD4020","V2009","V2005",
paste0("V",1028001:1028200))
# Carregar as informações
pnadc <- DBI::dbGetQuery(db,paste0('select ',
paste0('"',vars,'"',collapse = ","),
'from pnadc.pnadt202301'))
# Fazer o design
pnad_design <- survey::svrepdesign(data=pnadc, # Objeto com os dados
weight=~V1028, # Peso
type="bootstrap", # Tipo de estimativa
repweights="V1028[0-9]+", # Pesos replicados
mse=TRUE, # variância baseada na soma dos quadrados ao redor da estimativa pontual
replicates=length(sprintf("V1028%03d",
seq(1:200))), # n replicações
df=length(sprintf("V1028%03d", # graus de liberdade
seq(1:200))))
# Deixar como tibble (para utilizar o pacote srvyr)
pnad_design <-srvyr::as_survey(pnad_design)
Pronto! Com o objeto pnad_design podemos fazer
estimativas para a população, partindo dos dados amostrais. Vamos testar
estimando o total da população brasileira. O nosso objeto base agora
será o pnad_design, com o qual utilizaremos o pacote
srvyr. Com a parâmetro vartype='ci', obtemos
as estimativas dos intervalos de confiança. Podemos, também, utilizar o
parâmetro “cv” dentro do vartype para calcular o
coeficiente de variação.
# População DF com mais de 18 anos
pop18 <- pnad_design %>%
# Filtrar somente a população com 18 anos ou mais de idade
srvyr::filter(V2009>=18) %>%
# Criar uma variável auxiliar para contagem
srvyr::mutate(count=1) %>%
# Calcular o total da população, com seu intervalo de confiança
srvyr::summarise(n=survey_total(count, vartype = c("ci","cv")))
Verificamos que existiam entre 161.971.029 e 162.206.376 pessoas com mais de 18 anos no Brasil no primeiro trimestre de 2023, sendo o valor pontual de 162.088.702 pessoas.
Repare que, para calcular essas estimativas, foi necessário pegar do banco 201 variáveis de peso, o que significa um alto custo computacional de partida. Existe uma outra maneira de obter essas estimativas, com os mesmos valores pontuais, mas com variâncias ligeiramente diferentes. Para isso, necessitaremos das seguintes variáveis:
- O código da UPA (Unidade Primária de Amostragem):
UPA; - O ID do domicílio, composto pela junção da UPA, do número de seleção
do domicílio e do painel de seleção:
UPA,V1008eV1014; - O estrato do desenho amostral:
Estrato; - O peso trimestral com correção de não entrevista SEM calibração pela
projeção de população:
V1027; - Os domínios de projeção geográficos:
posest; - A projeção da população por níveis geográficos:
V1029; - Os domínios de projeção por sexo e idade:
posest_sxi; - A projeção da população por sexo e idade:
V1033.
Com essas informações, iremos informar ao pacote survey
o desenho inicial da pesquisa e a pós-estratificação, que seria as
projeções populacionais para os domínios informados anteriormente.
# Definir variáveis
vars <- c("UF","V1028","V1022","VD4020","V2009","V2005","V2007","V2001",
"UPA","V1008","V1014","Estrato","V1027","posest",
"V1029","posest_sxi","V1033")
# Puxar os dados
pnadc <- DBI::dbGetQuery(db,paste0('select ',
paste0('"',vars,'"',collapse = ","),
'from pnadc.pnadt202301'))
# Ajustar tipo das variáveis
pnadc <- pnadc %>%
dplyr::mutate(ID_DOMICILIO=paste0(UPA,V1008,V1014)) %>%
dplyr::mutate_at(vars(UPA,Estrato,posest,posest_sxi),
list(~as.character(.)))
# Fazer o desenho inicial
desenho_inicial <- survey::svydesign(ids=~UPA+ID_DOMICILIO, # Ids
strata=~Estrato, # Estratos do desenho da amostra da PNADC
data=pnadc,# Base de dados
weights=~V1027, # Pesos
nest=TRUE # Ajuster dos IDs dentro dos estratos
)
# Totais populacionais por pós-estratos geográficos
popc.types <- pnadc %>%
# Agrupar pelos estratos
dplyr::group_by(posest) %>%
# Sumarizar
dplyr::summarise(Freq=first(V1029)) %>%
# Desagrupar
dplyr::ungroup() %>%
# Ordenar os dados
dplyr::arrange(posest)
# Totais populacionais por pós-estratos de sexo e idade
popi.types <- pnadc %>%
# Agrupar os dados
dplyr::group_by(posest_sxi) %>%
# Sumarizar
dplyr::summarise(Freq=first(V1033)) %>%
# Desagrupar
dplyr::ungroup() %>%
# Ordenar os dados
dplyr::arrange(posest_sxi)
# Criar objeto com as informações populacionais para o raking
pop.rake.calib <- c(sum(popc.types$Freq),
popc.types$Freq[-1],
popi.types$Freq[-1])
# Declarar o plano amostral
pnad_design <- survey::calibrate(design=desenho_inicial, # Desenho inicial
formula=~posest+posest_sxi, # Definição da cobinação para o raking
pop=pop.rake.calib, # informações populacionais
calfun="raking", # Método
aggregate.stage=2, # Estágios
bounds=c(0.2,5), # limites
multicore=TRUE, # Usar multiprocessamento
sparse=TRUE # Para calcular mais rápido (matriz esparsa)
)
# Ajustar para tratamento de estratos com apenas uma UPA (adjust=centered)
options(survey.lonely.psu = "adjust")
# Ajustar objeto de amostra, para uso com o pacote srvyr (como tibble)
pnad_design <- srvyr::as_survey(pnad_design)
Vamos rodar novamente nossas estimativas para a população brasileira com 18 anos ou mais.
# População DF com mais de 18 anos
pop18 <- pnad_design %>%
# Filtrar somente a população com 18 anos ou mais de idade
srvyr::filter(V2009>=18) %>%
# Criar uma variável auxiliar para contagem
srvyr::mutate(count=1) %>%
# Calcular o total da população, com seu intervalo de confiança
srvyr::summarise(n=survey_total(count, vartype = "ci"))
Agora, verificamos que existiam entre 161.976.980 e 162.200.424 pessoas com mais de 18 anos no Brasil no primeiro trimestre de 2023, sendo o valor pontual de 162.088.702 pessoas, exatamente o mesmo calculado anteriomente.
Assim, caso existam limitações computacionais, esse método pode ser utilizado, ressalvando-se as diferenças existentes nas estimativas das variâncias.
Caso o desejo fosse estimar esse mesmo total por UF, isso poderia ser
feito com a função group_by(). Vamos aproveitar e calcular
o percentual de cada grupo no total.
pnad_design %>%
# Filtrar somente a população com 18 anos ou mais de idade, retirando os códigos de não informação
srvyr::filter(V2009>=18) %>%
# Informar o grupo que queremos a informação
srvyr::group_by(UF) %>%
# Calcular o total e o Percentual da população, com seu intervalo de confiança
srvyr::summarise(n=survey_total(vartype = "ci"),
# Calcular o percentual da população
pct=survey_mean(vartype = "ci"))
Note que, desta vez, não foi preciso criar um contador. Quando utilizamos a função de agrupamento de um fator, seguida da função de sumarização, os totais e percentuais são calculados sem a necessidade de informar o argumento.
Vamos calcular a rendimento do trabalho nominal e real para o Brasil, sem considerar e considerando a expansão dos resultados.
pnad_design %>%
# Calcular o rendimento médio do trabalho
srvyr::summarise(renda_real=survey_mean(VD4020*inflacao_br,na.rm=T,vartype="ci"),
renda=survey_mean(VD4020,na.rm=T,vartype="ci"))
# Rendimento sem expansão
mean(pnadc$VD4020,na.rm=T)
Por essa metodologia, a renda nominal estimada foi de R$ 3.118, com intervalo de R$ 3.055 e R$ 3.180. Em termos reais (maio/2023), o valor estimado é de R$ 3.144, com intervalo de R$ 3.080 a R$ 3.207. Sem expansão, ou seja, a renda amostral, foi de R$ 2.839.
Outras manipulações recorrentes
Vamos agora elencar algumas variáveis para construirmos um pequeno relatório. Vamos construir gráficos e tabelas para: população, por faixa etária e sexo; distribuição do rendimento do trabalho (nominal), por faixas; e número de moradores no domicílio. E montar um mini relatório com essas informações.
As informações serão criadas com a função mutate(), as
faixas de idade e de rendimento serão criadas com auxílio da função
cut(). Ao final, utilizaremos a função
mutate_if() para transformar as variáveis do tipo
character em fator e, por fim, utilizaremos a função
select() para selecionar as variáveis desejadas. Para criar
as faixas de rendimento, consideraremos o número de salários mínimos,
vigente em 2023.
# Criar um objeto com o salário mínimo em 2023
sm <- 1320
# Criar um objeto com as variáveis de interesse
vars_relatorio <- pnad_design %>%
# Criar variável de sexo
srvyr::mutate(sexo=case_when(V2007==1~"Homem",
V2007==2~"Mulher"),
# Criar variável de faixas de idade
idade_faixas=cut(V2009,
breaks = c(-Inf,seq(4,74,by=5),Inf),
labels = c("0 a 4 anos","5 a 9 anos",
"10 a 14 anos","15 a 19 anos",
"20 a 24 anos","25 a 29 anos",
"30 a 34 anos","35 a 39 anos",
"40 a 44 anos","45 a 49 anos",
"50 a 54 anos","55 a 59 anos",
"60 a 64 anos","65 a 69 anos",
"70 a 74 anos","Mais de 75 anos"),
ordered_result = T),
# Criar variável de faixas de salário do trabalho principal
faixas_salario=cut(VD4020,
breaks = c(-Inf,sm,2*sm,4*sm,10*sm,20*sm,Inf),
labels = c("Até 1 salário","Mais de 1 até 2 salários",
"Mais de 2 até 4 salários",
"Mais de 4 até 10 salários",
"Mais de 10 até 20 salários",
"Mais de 20 salários")),
# Criar variável para as UFs
UF=factor(UF,
levels=c(11:17,
21:29,
31:33,35,
41:43,
50:53),
labels=c('Rondônia',
'Acre',
'Amazonas',
'Roraima',
'Pará',
'Amapá',
'Tocantins',
'Maranhão',
'Piauí',
'Ceará',
'Rio Grande do Norte',
'Paraíba',
'Pernambuco',
'Alagoas',
'Sergipe',
'Bahia',
'Minas Gerais',
'Espírito Santo',
'Rio de Janeiro',
'São Paulo',
'Paraná',
'Santa Catarina',
'Rio Grande do Sul',
'Mato Grosso do Sul',
'Mato Grosso',
'Goiás',
'Distrito Federal'))) %>%
# Transformar em fator variáveis do tipo character
srvyr::mutate_if(is.character,list(~factor(.))) %>%
# Selecionar as variáveis criadas e algumas variáveis auxiliares
srvyr::select(UF,sexo,idade_faixas,faixas_salario)
Criado esse objeto auxiliar com as variáveis desejadas, vamos
calcular os totais para cada um dos grupos, juntamente com seus
intervalos de confiança. Para isso, vamos utilizar as funções
group_by(), para conseguirmos agrupar os dados pelas
categorias desejadas e a função summarise(), que calculará
os totais ou proporções para cada grupo. Os intervalos de confiança são
calculados com a função vartype="ci".
# Construir um objeto com as idades calculadas, por faixas de idade e sexo
# para montarmos a pirâmide etária
piramide <- vars_relatorio %>%
# Agrupar por faixas de idade e sexo
srvyr::group_by(idade_faixas,sexo) %>%
# Calcular os totais
srvyr::summarise(n=survey_total(na.rm = T, vartype = "ci"))
# Fazer o gráfico com a pirâmide
piramide_grafico <- piramide %>%
# Construir um plot com as idades no eixo x, as quantidades no eixo y,
# preenchimento com a variável sexo, e os intervalos de confiança
# inferiores e superiores
ggplot(aes(x=idade_faixas,y=n, fill=sexo, ymin=n_low,ymax=n_upp))+
# Fazer o gráfico de barras para o sexo Feminino
geom_bar(data = dplyr::filter(piramide, sexo == "Mulher"),
stat = "identity") +
# Fazer o gráfico de barras para o sexo Masculino
geom_bar(data = dplyr::filter(piramide, sexo == "Homem"),
stat = "identity",
position = "identity",
# Negativar os valores para espelhar no eixo
mapping = aes(y = -n))+
# Plotar os erros para o sexo Masculino, negativando os valores para espelhar o eixo
geom_errorbar(data = dplyr::filter(piramide, sexo == "Homem"),
mapping = aes(ymin = -n_low,ymax=-n_upp),
width=0,
color="black")+
# Plotar os erros para o sexo Feminino
geom_errorbar(data = dplyr::filter(piramide, sexo == "Mulher"),
width=0,
color="black")+
# Inverter os eixos, fazendo com que o gráfico de colunas verticais fique
# horizontal
coord_flip() +
# Ajustar as configurações de escala
scale_y_continuous(labels = function(x) format(abs(x),
big.mark = ".",
scientific = FALSE,
decimal.mark=",")) +
# Suprimir os nomes dos eixos
labs(x="",y="") +
# Suprimir o nome da legenda
scale_fill_discrete(name = "")
# Plotar gráfico
piramide_grafico
Para montar a pirâmide, usamos duas vezes a função
geom_bar(), uma para desenhar a distribuição etária
feminina e outra a masculina. Como o formato desejado é a pirâmide,
escolhemos uma das categorias e negativamos seus valores, para que ela
seja apresentada na direção oposta da abscissa. O mesmo procedimento
deve ser adotado para as informações dos erros amostrais, desenhados com
a função geom_errorbar(). Para que as informações sejam
apresentadas em barras horizontais, ao invés de verticais, usamos a
função coord_flip(), que inverte as coordenadas do gráfico.
Por fim, realizamos alguns ajustes de apresentação das informações,
retirando os nomes dos eixos com a função labs(), retirando
o nome da legenda com a função scale_fill_discrete() e
alterando a formatação numérica dos labels com a função
scale_y_continuos(). Note que, para isso, criamos uma
função com uma série de argumentos de formação: valor absoluto
abs(), alteramos a forma de exibição do separador decimal e
acrescentamos um separador de milhar por ponto.
Para construir o gráfico com os salários, os passos são análogos aos
realizados para construção do gráfico anterior. A única diferença é que
agora utilizamos a função theme() para retirar a legenda da
apresentação dos dados.
# Construir um objeto com as informações de salário
salario <- vars_relatorio %>%
dplyr::filter(is.na(faixas_salario)==F) %>%
# Agrupar por faixas de salário
srvyr::group_by(faixas_salario) %>%
# Calcular os totais para cada grupo de salário
srvyr::summarise(n=survey_total(na.rm=T,vartype = "ci")) %>%
# Retirar NA
na.omit
# Construir um objeto com o gráfico
salario_grafico <- salario %>%
# Plotar os eixos x e y
ggplot(aes(x=faixas_salario, y=n))+
# Construir o gráfico de barras
geom_bar(stat = "identity") +
# Construir as barras de erro
geom_errorbar(aes(ymin=n_low,ymax=n_upp,linewidth=4, width=0), color="darkred")+
# Inverter os eixos
coord_flip()+
# Suprimir o nome dos eixos
labs(x="",y="")+
# Retirar o título da legenda
theme(legend.position="none")+
# Ajustar as formatações de escala
scale_y_continuous(labels = function(x) format(abs(x),
big.mark = ".",
scientific = FALSE,
decimal.mark=","))
# Plotar gráfico
salario_grafico
Caso o desejo fosse saber a situação de salários por UF, poderíamos
fazer isso facilmente com a função facet_wrap(). Vamos ver
como funciona, agora calculando o percentual de pessoas em cada faixa de
rendimento, para as 27 UFs.
# Carregar o pacote Scales
library(scales)
# Construir o objeto com os valores
salario2 <- vars_relatorio %>%
# Filtrar somente para casos válidos
srvyr::filter(is.na(faixas_salario)==FALSE) %>%
# Agrupar por UF e faixas de salário
srvyr::group_by(UF,faixas_salario) %>%
# Calcular as proporções por faixa de salário
srvyr::summarise(n=survey_mean(na.rm=T,vartype = "ci")) %>%
# Retirar NA
na.omit
# Construir o gráfico
salario2 %>%
# Plotar os eixos x e y
ggplot(aes(x=faixas_salario, y=n))+
# Construir o gráfico de barras
geom_bar(stat = "identity") +
# Construir o gráfico com os erros
geom_errorbar(aes(ymin=n_low,ymax=n_upp, group=UF),linewidth=1,width=0, color="darkred")+
# Inverter os eixos
coord_flip()+
# Suprimir o nome dos eixos
labs(x="",y="")+
# Suprimir o nome da legenda
theme(legend.position="none")+
# Ajustar as formatações de escala
scale_y_continuous(labels = scales::percent)+
# Plotar o gráfico para cada uma das RAs, divididas em 4 colunas
facet_wrap(.~UF, ncol=4)
Para o último gráfico, como estamos realizando uma estatística para o
domicílio, precisamos filtrar para selecionarmos apenas a informação do
responsável (cujo peso é utilizado para expandir os resultados
domiciliares). Fazemos isso com auxílio da função filter().
Como maneira de facilitar a leitura dos dados, adicionamos os valores
exatos de cada coluna com a função geom_text().
# Construir o objeto com o número de moradores
nmor <- pnad_design %>%
srvyr::filter(V2005==1) %>%
srvyr::mutate(# Criar variável para o número de pessoas no domicílio
nmor=factor(case_when(V2001==1~"Unipessoal",
V2001==2~"2 pessoas",
V2001==3~"3 pessoas",
V2001==4~"4 pessoas",
V2001>=5~"5 ou mais pessoas"))) %>%
# Agrupar por situação de esgotamento sanitário
srvyr::group_by(nmor) %>%
# Calcular a proporção de cada grupo
srvyr::summarise(n=survey_mean(na.rm = T,vartype = "ci"))
# Construir o objeto com o gráfico
nmor_grafico <- nmor %>%
# Plotar os eixos x e y, reordenando os fatores, do maior para o menor resultado
ggplot(aes(x=fct_reorder(nmor,-n),y=n,ymin=n_low,ymax=n_upp))+
# Construir o gráfico de barras
geom_bar(stat = "identity")+
# Construir os erros
geom_errorbar(size=4, width=0,
color="black")+
# Ajustar os nomes dos eixos
labs(x="",y="%")+
# Retirar o nome da legenda
theme(legend.position="none")+
# Ajustar a formatação dos rótulos
scale_y_continuous(labels = scales::percent)+
# Inserir informações dos resultados no gráfico
geom_text(aes(label = paste0(round(100*n,0),"%")),
size=4, fontface = "bold",
vjust = -0.25,hjust=1.25)
# Plotar grafico
nmor_grafico
Vamos ver como fazer um gráfico de setores, com as mesmas informações
anteriores. Note que, para fazer esse tipo de gráfico, perderemos as
informações dos intervalos de confiança. Para que o gráfico fique mais
elegante, criamos um tema retirando todos os elementos básicos,
atribuindo-o a um objeto chamado tema_branco. Para esse
tipo de gráfico, precisamos da função coord_polar(), para
colocar o gráfico em coordenada polar. Com isso, o posicionamento dos
rótulos ficam um pouco mais complexos, sendo necessário criar uma
variável com a posição do label.
# Carregar o pacote ggrepel
library(ggrepel)
# Construir o objeto com as informações do número de moradores
nmor2 <- pnad_design %>%
srvyr::filter(V2005==1) %>%
srvyr::mutate(# Criar variável para o número de pessoas no domicílio
nmor=factor(case_when(V2001==1~"1 Unipessoal",
V2001==2~"2 pessoas",
V2001==3~"3 pessoas",
V2001==4~"4 pessoas",
V2001>=5~"5 ou mais pessoas"))) %>%
# Agrupar por situação de esgotamento sanitário
srvyr::group_by(nmor) %>%
# Calcular a proporção de cada grupo
srvyr::summarise(n=survey_mean(na.rm = T,vartype = "ci")) %>%
# Deixar as informações em ordem decrescente
dplyr::arrange(-n) %>%
# Construir uma variável auxiliar, com a posição do label
dplyr::mutate(pos=cumsum(n)-n/10)
# Criar o tema branco, eliminando todos os elementos gráficos padrões
tema_branco <- theme_minimal()+
theme(
# Retirar título do eixo x
axis.title.x = element_blank(),
# Retirar título do eixo y
axis.title.y = element_blank(),
# Retirar as bordas no painel
panel.border = element_blank(),
# Retirar elementos textuais do eixo y
axis.text.y = element_blank(),
# Retirar demais elementos textuais dos eixos
axis.text = element_blank(),
# Retirar as linhas de grade
panel.grid=element_blank(),
# Retirar os ticks
axis.ticks = element_blank())
# Construir o gráfico de setores
nmor2 %>%
# Plotar o gráfico, com as quantidades no eixo y, o preenchimento com as categorias,
# reordenando as quantudades, e o valor 1 para travar o eixo x
ggplot(aes(x=1,y=n,fill=fct_reorder(nmor,n)))+
# Construir as "barras"
geom_bar(stat="identity")+
# Transformar em coordenada polar o eixo y, com início em 0
coord_polar("y", start=0)+
# Retirar os nomes dos eixos
labs(x="",y="") +
# Adicionar o tema branco
tema_branco+
# Retirar o nome da legenda
scale_fill_discrete(name="")+
# Adicionar o label com os valores, usando a função repel para evitar
# sobreposições
geom_text_repel(aes(label = scales::percent(n), y=pos), size=5, color="white",
fontface="bold")
Alternativamente ao gráfico de setores, podemos fazer um gráfico de coluna agrupada, que fornece o mesmo tipo de informação para este caso.
pnad_design %>%
srvyr::filter(V2005==1) %>%
srvyr::mutate(# Criar variável para o número de pessoas no domicílio
nmor=factor(case_when(V2001==1~"1 Unipessoal",
V2001==2~"2 pessoas",
V2001==3~"3 pessoas",
V2001==4~"4 pessoas",
V2001>=5~"5 ou mais pessoas"))) %>%
# Agrupar por situação de esgotamento sanitário
srvyr::group_by(nmor) %>%
# Calcular a proporção de cada grupo
srvyr::summarise(n=survey_mean(na.rm = T,vartype = "ci")) %>%
# Gerar uma área de plotage,
ggplot()+
# Gerar a geometria da barra
geom_bar(aes(x=1,y=n,fill=nmor),stat = "identity",alpha=0.5) +
# Adicionar os percentuais ao gráfico, na forma de texto
geom_text(aes(x=1, label = paste0(format(abs(round(n*100)),
big.mark = ".",
scientific = FALSE,
decimal.mark=","),"%"),
y= n,
group = nmor),
size=4,
fontface = "bold",
color = "black",
position = position_stack(vjust = .5)) +
# Retirar o nome da legenda
scale_fill_manual(name="",values=RColorBrewer::brewer.pal(5, "Dark2"))+
# Ajustar o label da escala y
scale_y_continuous(labels = scales::percent)+
# Retirar o rótulo dos eixos
labs(x="",y="")+
# Retirar as informações do eixo x
theme(axis.line.x = element_blank(),
axis.ticks.x = element_blank(),
axis.text.x=element_blank())
Criando relatórios com o Rmarkdown
Agora que fizemos todos esses objetos contendo nossos gráficos, vamos
criar um pequeno relatório com essas informações. Para isso, vamos
precisar salvar nossos objetos, para que não seja necessário criarmos
todos eles novamente dentro do documento. Basicamente, podemos salvar os
objetos do R em alguns formatos, como o rda e o
rds, ou em formatos utilizados por outros softwares
estatísticos, com o pacote foreign. Uma maneira rápida de
salvar todos os seus objetos disponíveis no ambiente em um único arquivo
é utilizando a função save.image(). Utilize a opção
compress = T para reduzir o tamanho do arquivo a ser
criado. Para salvar somente os objetos de interesse, utilize a função
save().
# Salvar um arquivo com todos os objetos
save.image("dados/objetos.rda", compress = T)
# Remover todos os objetos do ambiente
# rm(list = ls())
# Carregar os objetos salvos
load("dados/objetos.rda")
# Salvar somente objetos de interesse
# save(list=c("piramide","nmor","salario"),
# file="dados/objetos.rda")
Muitas vezes não precisamos salvar todo o nosso diretório e queremos
apenas salvar um objeto específico, como um determinado banco de dados
ou apenas os objetos que iremos utilizar no nosso relatório. Para isso,
utilizamos a função saveRDS(). Vamos salvar os três
gráficos que criamos anteriormente, neste formato.
# Salvar os objetos no formato RDS
saveRDS(piramide,"dados/piramide.rds")
saveRDS(nmor,"dados/nmor.rds")
saveRDS(salario,"dados/salario.rds")
Feito isso, agora vamos criar nosso relatório. Para isso, abra um
novo arquivo R markdown, clicando no atalho para novo arquivo ->
R Markdown. Selecione a opção PDF, escolha um nome para o
arquivo e clique em ok.
Os arquivos gerados no R em pdf são baseados na linguagem \(\LaTeX\). Assim, é possível adicionar os pacotes e definições utilizados no \(\LaTeX\) diretamente no R. Os relatório básicos já estão pré-configurados no R, sem que sejam necessários maiores ajustes.
Assim que criamos um novo arquivo, um modelo de relatório é
automaticamente gerado. A estrutura básica é composta por um preâmbulo,
no qual inserimos algumas informações sobre a estrutura e a configuração
do markdown. Este preâmbulo fica encapsulado entre três traços
---, nos quais indicamos uma série de formatações,
inclusive o tipo do output que será gerado, que é o PDF no
nosso caso. Podemos gerar ainda documentos em word ou html. Este curso,
por exemplo, foi escrito em um arquivo markdown, tendo como
output o formato HTML.
Os códigos de R podem ser inseridos juntamente com os textos, dentro
de acentos graves ``, com a primeira letra sendo o
r. Podemos criar também os chunks, que são
estruturas separadas para inserções no texto, como tabelas e figuras. Os
chunks são encapsulados por uma sequência de três
acentos graves```, sendo a parte superior composta ainda de
parâmetros inseridos entre chaves {r}, iniciando com a
letra r. Você pode criar chunks com outras linguagens de programação,
como python, seguindo o exemplo abaixo.
# ```{python}
# 1+1
# ```
# `r rnow(pnadc)` Isto é um código r dentro de um texto markdown
# Abaixo temos um exemplo de chunk
#```{r}
# table(pnadc$UF)
#```
Os títulos das seções são criados com o símbolo #. Caso
queiramos criar subseções, vamos adicionando sequências do mesmo
símbolo.
Após ser escrito o relatório, precisamos compilar o documento, que é
realizado com o auxílio dos pacotes knit e
pandoc. O primeiro deles cria um arquivo com os elementos
textuais e do R, no formato .md, que posteriormente é
convertido para o formato desejado com o segundo pacote.
Rode o arquivo de exemplo, clicando no botão knit, para
verificar o resultado. O RStudio pedirá para você indicar o nome e o
local do arquivo a ser criado. Toda vez que você “tricotar” o documento,
o R salva e executa todos os passos elencados anteriormente
automaticamente.
Vamos agora criar o nosso relatório. Para isso, vamos utilizar apenas
cinco pacotes do \(\LaTeX\), o
babel, para conseguirmos produzir o relatório em português,
o pacote inputenc, que cuidará do encoding dos caracteres,
o float, que cuidará das imagens e os pacotes
booktabs e tabu para a confecção das tabelas.
Fazemos isso adicionando no preâmbulo do documento a linha
header-includes:, indicando os pacotes do \(\LaTeX\) a serem utilizados. Qualquer outro
pacote pode ser inserido neste espaço. Para rodar o relatório em PDF,
você precisará ter alguma distribuição do TeX/LaTeX. Uma
opção em Windows é MiKTeK.
Durante a instalação, marque a opção “Install missing packages
on-the-fly” como “yes”. O RStudio server já conta com uma
instalação em sua máquina.
Comumente, utilizamos o primeiro chunk para inserir as
configurações e opções a serem utilizadas no decorrer do documento. Note
que utilizamos a opção include=FALSE para que este
chunk não seja incluído no documento. Nele, carregamos os
pacotes necessários, ajustamos as configurações padrão dos demais
chunks, carregamos a base e ajustamos uma configuração do
pacote kableExtra, que será utilizado para gerar nossas
tabelas no formato \(\LaTeX\).
No meio do documento, podemos utilizar qualquer comando \(\LaTeX\), da mesma maneira que faríamos
caso estivéssemos trabalhando com a ferramenta. Alguns atalhos facilitam
uma série de formatações, como palavras em itálico, escritas entre
asteriscos *palavra* e negrito, escritas entre duplos
asteriscos **palavra**. Notas de rodapé são facilmente
inseridas entre colchetes, precedido de um acento circunflexo
^[nota de rodapé].
Para inserirmos uma figura criada com o pacote ggplot,
devemos “abrir” um chunk e chamar o objeto dentro dele. Para
inserir o título da figura e seu respectivo label, utilizamos a
opção fig.cap="Título", no início do chunk. O
label deve ser adicionado por dentro do título, com o comando
\\label{}, este último derivado do \(\LaTeX\). Repare que, neste caso, foi
necessário inserir uma segunda barra invertida, de modo que o R entenda
que estamos querendo utilizar um comando do \(\LaTeX\) dentro do chunk.
Alternativamente, você pode nomear o chunk e utilizar como
referência fig:nome do chunk. Para fazer referência ao
elemento, utilize o comando \ref{} dentro do texto.
Para as tabelas, utilizamos o pacote knitr, usualmente
em conjunto com o pacote kableExtra para customizarmos as
tabelas. Diferentemente das figuras, este pacote já esta preparado para
receber as informações de título em parâmetros específicos, convertendo
o resultado para a linguagem \(\LaTeX\). Para algumas formatações
adicionais, como separador de milhar, posicionamento da tabela e
marcador decimal, a própria função kable() pode ser
utilizada. Para referenciar as tabelas, utilize
tab:nome do chunk. Abaixo está um exemplo de relatório, que
deve ser executado em um arquivo .Rmd, bastando retirar os
sustenidos.
# ---
# title: "Mini relatório da PNADC"
# author: "Thiago Mendes Rosa"
# date: "`r Sys.Date()`"
# output:
# pdf_document: default
# word_document: default
# header-includes:
# - \usepackage[brazilian]{babel}
# - \usepackage[utf8]{inputenc}
# - \usepackage{float}
# - \usepackage{booktabs}
# - \usepackage{tabu}
# ---
# ```{r setup, include=FALSE}
# library(forcats)
# library(scales)
# knitr::opts_chunk$set(echo = F,fig.pos = 'H',warning=F)
# # Carregar objetos
# load("dados/objetos.rda")
# # Definir função para separador de milhar e decimal dos chunks
# knitr::knit_hooks$set(inline = function(x) {
# prettyNum(x, big.mark=".",decimal.mark = ",")
# })
# options(kableExtra.latex.load_packages = FALSE)
# # Habilitar opção abaixo para gerar tabelas em word. Para tanto,
# # retirar o argumento "latex" da função "kable"
# #options(kableExtra.auto_format = FALSE)
# library(kableExtra)
# ```
#
# # PNADC - 1º Trimestre de 2023
#
# A PNADC visitou **`r nrow(pnadc[pnadc$V2005==1,])`** domicílios e coletou informações de `r nrow(pnadc)` moradores.
#
# ## Estrutura etária
#
# A estrutura etária dos moradores do Brasil é apresentada Figura \ref{fig:piramide}.
#
# ```{r piramide, fig.cap="Pirâmide etária",out.extra=''}
# piramide_grafico
# ```
#
# Os valores específicos podem ser verificados na tabela \ref{tab:piramide.tab}.
#
# ```{r piramide.tab, results='asis'}
# piramide %>%
# knitr::kable("latex",
# caption="Pirâmide etária",
# booktabs = T,
# digits = 0,
# format.args=list(big.mark = ".",
# decimal.mark = ",")) %>%
# kableExtra::kable_styling(latex_options = c("HOLD_position"),
# full_width=T) %>%
# kableExtra::footnote(general_title ="",
# general="Fonte: PNADC 2023 - 1º Tri",
# fixed_small_size=T)
# ```
# \clearpage
#
# ## Salários
#
# No que diz respeito aos salários, sua distribuição por faixas de salário mínimo^[O salário considerado foi de R$ 1.320,00] é apresentada Figura \ref{fig:salarios}.
#
# ```{r salarios, fig.cap="Salarios por faixa de SM",out.extra=''}
# salario_grafico
# ```
#
# Os dados podem ser consultados na Tabela \ref{tab:salarios.tab}.
#
# ```{r salarios.tab, results='asis'}
# salario %>%
# knitr::kable("latex",
# caption="Salarios por faixa de SM",
# booktabs = T,
# linesep = "",
# format.args=list(big.mark = ".",
# decimal.mark = ",")) %>%
# kableExtra::kable_styling(latex_options = c("HOLD_position"),
# full_width=T) %>%
# kableExtra::column_spec(1,width = "5cm") %>%
# kableExtra::footnote(general_title ="",
# general="Fonte: PNADC 2023 - 1º Tri",
# fixed_small_size=T)
# ```
# \clearpage
# \pagebreak
#
# ## Número de moradores por domicílio
#
# Por fim, a distribuição do número de moradores é apresentada na Figura \ref{fig:nmor}
#
# ```{r nmor, fig.cap="Esgotamento sanitário",out.extra=''}
# esgotamento_grafico
# ```
#
# Os números podem ser consultados na Tabela \ref{tab:nmor.tab}.
#
# ```{r nmor.tab, results='asis'}
# nmor %>%
# knitr::kable("latex",
# caption="Esgotamento sanitário",
# booktabs = T,
# digits = 2,
# format.args=list(big.mark = ".",
# decimal.mark = ",")) %>%
# kableExtra::kable_styling(latex_options = c("HOLD_position"),
# full_width=T) %>%
# kableExtra::column_spec(1,width = "6cm") %>%
# kableExtra::footnote(general_title ="",
# general="Fonte: PNADC 2023 - 1º Tri",
# fixed_small_size=T)
# ```
O relatório criado em PDF pode ser facilmente gerado em outros
formatos. Experimento clicar no botão knit, na seta para baixo,
selecionando a opção Knit to Word. O relatório também pode
ser gerado no formato HTML, todavia as tabelas necessitam
de alguns ajustes neste caso. Devemos alterar o tipo da tabela para
"html", com o argumento format, dentro da
função knitr::kable(). Alternativamente, podemos utilizar
as funções xtable::xtable() ou
pander::pander().
Salvando seus resultados no Github
Para configurar suas credenciais no github, digite na aba do terminal os seguintes comandos:
- git config --global user.name “seu nome de usuário”
- git config --global user.email “seu e-mail”
Se quiser configurar sua senha, digite:
- git config --global user.password “sua senha”
Depois de produzirmos nossos códigos, vamos subir as informações para o nosso repositório no GitHub. Para isso, temos três opões:
- Clicar no botão de atalho do GitHub na barra superior
- Clicar na janela superior à direita, na aba do Git
- Usar o atalho de teclado
Ctrl+Alt+M.
Pelo primeiro e terceiro métodos, a janela abaixo será exibida. Com o
segundo método, a janela aparece depois de clicar no botão
commit.
Com ela, verificamos todos os objetos que foram modificado, removido
e/ou adicionados no diretório do projeto. A partir dele, devemos
informar o que desejamos fazer com cada um deles. Podemos ignorá-los com
o botão Ignore, para, neste caso, indicarmos que não
desejamos que essa informação seja armazenada no repositório.
Para os arquivos que queremos armazenar, devemos selecionar e
utilizar o botão Stage. Após selecionarmos os arquivos a
serem enviados, devemos adicionar um cometário geral, para termos noção
do que se refere aquela etapa do projeto, e utilizar o botão
Commit. Com isso, nossos arquivos já estão prontos para
serem enviados ao repositório. A última etapa consiste em utilizar o
botão Push, que, após acionado, solicitará a confirmação do
usuário e senha. Pronto! Seus scripts e arquivos já estão armazenados e
versionados no Github. Caso queria continuar o projeto em outro local ou
compartilhar as informações com alguém, basta a pessoa fazer um
Pull do repositório.
Encerramento
Esse foi o mini-curso de R aplicado à PNADC O R é uma ferramenta muito ampla, que permite diversas outras aplicações, principalmente na área estatística. Aqui foi apresentada uma modesta parcela das funcionalidades que esta ferramenta pode oferecer. Ainda há muito mais a ser explorado. Utilizar o R constantemente fará com que você acumule habilidades e avance cada vez mais na utilização desta ferramenta. O começo pode parecer desafiador, mas, uma vez rompida a barreira inicial, o avanço se torna natural e prazeroso.
Abaixo você tem uma lista de aplicações analíticas sendo realizadas atualmente com o auxílio do R, segundo o blog revolution analytics.
Expanda seus conhecimentos e compartilhe!
Análises
- Matemática básica
- Estatística básica
- Distribuições de probabilidade
- Análise de Big Data
- Machine Learning
- Otimização e programação matemática
- Processamento de sinais
- Simulações e Geração de números aleatórios
- Modelagem estatística
- Teste estatísticos
Visualização e gráficos
- Gráficos estáticos
- Gráficos dinâmicos
- Mapas
- Dispositivos e formatos
Aplicações em R e Extensões ***
- Aplicações
- Mineração de dados
- Metodologia estatística
Qualquer dúvida, mande um e-mail para thiago.rosa@ipea.gov.br.
Exemplo extraído de: https://curso-r.github.io/ragmatic-book/principios.html#pipe.↩︎